Giter VIP home page Giter VIP logo

websockets-chat's Introduction

Laravel WebSocket chat server

Version Downloads License

logo

Requirements

  • Unix (extension pcntl_fork)
  • PHP 7.1+
  • Laravel 5
  • composer

Installing WebSockets Chat

The recommended way to install WebSockets is through Composer.

# Install Composer
curl -sS https://getcomposer.org/installer | php

Next, run the Composer command to install the latest stable version of WebSockets:

php composer.phar require ollyxar/websockets-chat

After updating composer, add the service provider to the providers array in config/app.php

Ollyxar\WSChat\WSChatServiceProvider::class,

Configuration

You can customize variables bellow by adding config-file: websockets-chat.php in the config folder:

parameter description example
handler Handler Class (extends of Worker) \App\MyHandler
host Host (ip) 0.0.0.0
port Port 2083
worker_count Count of forked process 4
use_ssl Used protocol false
cert PEM certificate /etc/nginx/conf.d/wss.pem
pass_phrase PEM certificate pass phrase secret$#%

Extended Handler class

This is example how to use Handler with User authentication. If you have default configuration and file-session-storage you can use this example.

First you have to install auth-helper:

php composer.phar require ollyxar/laravel-auth

Then create your Handler.php:

namespace App;

use Ollyxar\LaravelAuth\FileAuth;
use Ollyxar\WebSockets\Frame;
use Ollyxar\WebSockets\Worker;

/**
 * Class Handler
 * @package App
 */
class Handler extends Worker
{
    /**
     * Connected users
     *
     * @var array
     */
    protected $users = [];

    private function fillUser(array $headers, $socket): bool
    {
        if ($userId = FileAuth::getUserIdByHeaders($headers)) {
            // allow only one connection for worker per user
            if (!in_array($userId, $this->users)) {
                $this->users[(int)$socket] = $userId;
                return true;
            }
        }

        return false;
    }

    /**
     * @param $client
     */
    protected function onConnect($client): void
    {
        $userName = User::where('id', (int)$this->users[(int)$client])->first()->name;

        $this->sendToAll(Frame::encode(json_encode([
            'type'    => 'system',
            'message' => $userName . ' connected.'
        ])));
    }

    /**
     * @param array $headers
     * @param $socket
     * @return bool
     */
    protected function afterHandshake(array $headers, $socket): bool
    {
        return $this->fillUser($headers, $socket);
    }

    /**
     * @param $clientNumber
     */
    protected function onClose($clientNumber): void
    {
        $userName = User::where('id', (int)$this->users[$clientNumber])->first()->name;

        $this->sendToAll(Frame::encode(json_encode([
            'type'    => 'system',
            'message' => $userName . " disconnected."
        ])));
        
        unset($this->users[$clientNumber]);
    }

    /**
     * @param string $message
     * @param int $socketId
     */
    protected function onDirectMessage(string $message, int $socketId): void
    {
        $message = json_decode($message);
        $userName = User::where('id', (int)$this->users[$socketId])->first()->name;
        $userMessage = $message->message;

        $response = Frame::encode(json_encode([
            'type'    => 'usermsg',
            'name'    => $userName,
            'message' => $userMessage
        ]));

        $this->sendToAll($response);
    }
}

Then add markup to the front:

<div class="chat-wrapper">
    <div class="message-box" id="message-box"></div>
    <div class="panel">
        <input type="text" name="message" id="message" placeholder="Message"/>
        <button id="send-btn" class="button">Send</button>
    </div>
</div>

And JS code:

var wsUri = "ws://laravel5.dev:2083",
    ws = new WebSocket(wsUri);

ws.onopen = function () {
    var el = document.createElement('div');
    el.classList.add('system-msg');
    el.innerText = 'Connection established';
    document.getElementById('message-box').appendChild(el);
};

document.getElementById('message').addEventListener('keydown', function (e) {
    if (e.keyCode === 13) {
        document.getElementById('send-btn').click();
    }
});

document.getElementById('send-btn').addEventListener('click', function () {
    var mymessage = document.getElementById('message').value;

    if (mymessage === '') {
        alert("Enter Some message Please!");
        return;
    }

    var objDiv = document.getElementById("message-box");
    objDiv.scrollTop = objDiv.scrollHeight;

    var msg = {
        message: mymessage
    };
    ws.send(JSON.stringify(msg));
});

ws.onmessage = function (ev) {
    var msg = JSON.parse(ev.data),
        type = msg.type,
        umsg = msg.message,
        uname = msg.name;

    var el = document.createElement('div');

    if (type === 'usermsg') {
        el.innerHTML = '<span class="user-name">' + uname + '</span> : <span class="user-message">' + umsg + '</span>';
        document.getElementById('message-box').appendChild(el);
    }
    if (type === 'system') {
        el.classList.add('system-msg');
        el.innerText = umsg;
        document.getElementById('message-box').appendChild(el);
    }

    document.getElementById('message').value = '';

    var objDiv = document.getElementById('message-box');
    objDiv.scrollTop = objDiv.scrollHeight;
};

ws.onerror = function (e) {
    var el = document.createElement('div');
    el.classList.add('system-error');
    el.innerText = 'Error Occurred - ' + e.data;
    document.getElementById('message-box').appendChild(el);
};
ws.onclose = function () {
    var el = document.createElement('div');
    el.classList.add('system-msg');
    el.innerText = 'Connection Closed';
    document.getElementById('message-box').appendChild(el);
};

Starting WebSocket Server

php artisan websockets-chat:run

Sending direct message to the server

php artisan websockets-chat:send "Hello from system!"

websockets-chat's People

Contributors

alexslipknot avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.