2017 © Pedro Peláez
 

yii2-extension yii2-websocket

Yii2 websocket server component

image

consik/yii2-websocket

Yii2 websocket server component

  • Thursday, December 8, 2016
  • by consik
  • Repository
  • 8 Watchers
  • 28 Stars
  • 2,234 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 12 Forks
  • 0 Open issues
  • 3 Versions
  • 40 % Grown

The README.md

Yii2 WebSocketServer

Latest Stable Version Total Downloads License, (*1)

Used Ratchet, (*2)

Installation

The preferred way to install this extension is through composer., (*3)

Either run, (*4)

composer require consik/yii2-websocket

or add, (*5)

"consik/yii2-websocket": "^1.0"

WebSocketServer class description

Properties

  1. int $port = 8080 - Port number for websocket server
  2. bool $closeConnectionOnError = true - Close connection or not when error occurs with it
  3. bool $runClientCommands = true - Check client's messages for commands or not
  4. null|IoServer $server = null - IOServer object
  5. null|\SplObjectStorage $clients = null - Storage of connected clients

Methods

Events

  • EVENT_WEBSOCKET_OPEN

Class yii\base\Event - Triggered when binding is successfully completed, (*6)

  • EVENT_WEBSOCKET_CLOSE

Class yii\base\Event - Triggered when socket listening is closed, (*7)

  • EVENT_WEBSOCKET_OPEN_ERROR

Class events\ExceptionEvent - Triggered when throwed Exception on binding socket, (*8)

  • EVENT_CLIENT_CONNECTED

Class events\WSClientEvent - Triggered when client connected to the server, (*9)

  • EVENT_CLIENT_DISCONNECTED

Class events\WSClientEvent - Triggered when client close connection with server, (*10)

  • EVENT_CLIENT_ERROR

Class events\WSClientErrorEvent - Triggered when an error occurs on a Connection, (*11)

  • EVENT_CLIENT_MESSAGE

Class events\WSClientMessageEvent - Triggered when message recieved from client, (*12)

  • EVENT_CLIENT_RUN_COMMAND

Class events\WSClientCommandEvent - Triggered when controller starts user's command, (*13)

  • EVENT_CLIENT_END_COMMAND

Class events\WSClientCommandEvent - Triggered when controller finished user's command, (*14)

Examples

Simple echo server

Create your server class based on WebSocketServer. For example daemons\EchoServer.php:, (*15)

<?php
namespace app\daemons;

use consik\yii2websocket\events\WSClientMessageEvent;
use consik\yii2websocket\WebSocketServer;

class EchoServer extends WebSocketServer
{

    public function init()
    {
        parent::init();

        $this->on(self::EVENT_CLIENT_MESSAGE, function (WSClientMessageEvent $e) {
            $e->client->send( $e->message );
        });
    }

}

Create yii2 console controller for starting server:, (*16)

<?php
namespace app\commands;

use app\daemons\EchoServer;
use yii\console\Controller;

class ServerController extends Controller
{
    public function actionStart($port = null)
    {
        $server = new EchoServer();
        if ($port) {
            $server->port = $port;
        }
        $server->start();
    }
}

Start your server using console:, (*17)

php yii server/start, (*18)

Now let's check our server via js connection:, (*19)

var conn = new WebSocket('ws://localhost:8080');
    conn.onmessage = function(e) {
        console.log('Response:' + e.data);
    };
    conn.onopen = function(e) {
        console.log("Connection established!");
        console.log('Hey!');
        conn.send('Hey!');
    };

Console result must be:, (*20)

Connection established!, (*21)

Hey!, (*22)

Response:Hey!, (*23)

Handle server starting success and error events

Now we try handle socket binding error and open it on other port, when error occurs;, (*24)

Create yii2 console controller for starting server:, (*25)

<?php
namespace app\commands;

use consik\yii2websocket\WebSocketServer;
use yii\console\Controller;

class ServerController extends Controller
{
    public function actionStart()
    {
        $server = new WebSocketServer();
        $server->port = 80; //This port must be busy by WebServer and we handle an error

        $server->on(WebSocketServer::EVENT_WEBSOCKET_OPEN_ERROR, function($e) use($server) {
            echo "Error opening port " . $server->port . "\n";
            $server->port += 1; //Try next port to open
            $server->start();
        });

        $server->on(WebSocketServer::EVENT_WEBSOCKET_OPEN, function($e) use($server) {
            echo "Server started at port " . $server->port;
        });

        $server->start();
    }
}

Start your server using console command:, (*26)

php yii server/start, (*27)

Server console result must be:, (*28)

Error opening port 80, (*29)

Server started at port 81, (*30)

Recieving client commands

You can implement methods that will be runned after some of user messages automatically;, (*31)

Server class daemons\CommandsServer.php:, (*32)

<?php
namespace app\daemons;

use consik\yii2websocket\WebSocketServer;
use Ratchet\ConnectionInterface;

class CommandsServer extends WebSocketServer
{

    /**
     * override method getCommand( ... )
     *
     * For example, we think that all user's message is a command
     */
    protected function getCommand(ConnectionInterface $from, $msg)
    {
        return $msg;
    }

    /**
     * Implement command's method using "command" as prefix for method name
     *
     * method for user's command "ping"
     */
    function commandPing(ConnectionInterface $client, $msg)
    {
        $client->send('Pong');
    }

}

Run the server like in examples above, (*33)

Check connection and command working by js script:, (*34)

    var conn = new WebSocket('ws://localhost:8080');
    conn.onmessage = function(e) {
        console.log('Response:' + e.data);
    };
    conn.onopen = function(e) {
        console.log('ping');
        conn.send('ping');
    };

Console result must be:, (*35)

ping, (*36)

Response:Pong, (*37)

Chat example

In the end let's make simple chat with sending messages and function to change username;, (*38)

Code without comments, try to understand it by youself ;), (*39)

  • Server class daemons\ChatServer.php:
<?php
namespace app\daemons;

use consik\yii2websocket\events\WSClientEvent;
use consik\yii2websocket\WebSocketServer;
use Ratchet\ConnectionInterface;

class ChatServer extends WebSocketServer
{

    public function init()
    {
        parent::init();

        $this->on(self::EVENT_CLIENT_CONNECTED, function(WSClientEvent $e) {
            $e->client->name = null;
        });
    }


    protected function getCommand(ConnectionInterface $from, $msg)
    {
        $request = json_decode($msg, true);
        return !empty($request['action']) ? $request['action'] : parent::getCommand($from, $msg);
    }

    public function commandChat(ConnectionInterface $client, $msg)
    {
        $request = json_decode($msg, true);
        $result = ['message' => ''];

        if (!$client->name) {
            $result['message'] = 'Set your name';
        } elseif (!empty($request['message']) && $message = trim($request['message']) ) {
            foreach ($this->clients as $chatClient) {
                $chatClient->send( json_encode([
                    'type' => 'chat',
                    'from' => $client->name,
                    'message' => $message
                ]) );
            }
        } else {
            $result['message'] = 'Enter message';
        }

        $client->send( json_encode($result) );
    }

    public function commandSetName(ConnectionInterface $client, $msg)
    {
        $request = json_decode($msg, true);
        $result = ['message' => 'Username updated'];

        if (!empty($request['name']) && $name = trim($request['name'])) {
            $usernameFree = true;
            foreach ($this->clients as $chatClient) {
                if ($chatClient != $client && $chatClient->name == $name) {
                    $result['message'] = 'This name is used by other user';
                    $usernameFree = false;
                    break;
                }
            }

            if ($usernameFree) {
                $client->name = $name;
            }
        } else {
            $result['message'] = 'Invalid username';
        }

        $client->send( json_encode($result) );
    }

}
  • Simple html form chat.html:
Username:<br />
<input id="username" type="text"><button id="btnSetUsername">Set username</button>



Message:<br /> <input id="message" type="text"><button id="btnSend">Send</button>






Enjoy ;), (*40)

Other

Starting yii2 console application as daemon using nohup

nohup php yii _ControllerName_/_ActionName_ &, (*41)

The Versions

08/12 2016

dev-master

9999999-dev

Yii2 websocket server component

  Sources   Download

MIT

The Requires

 

by Sergey Poltaranin (Consik)

component yii2 websocket ratchet

07/12 2016

1.0.1

1.0.1.0

Yii2 websocket server component

  Sources   Download

MIT

The Requires

 

by Sergey Poltaranin (Consik)

component yii2 websocket ratchet

17/11 2016

1.0.0

1.0.0.0

Yii2 websocket server component

  Sources   Download

MIT

The Requires

 

by Sergey Poltaranin (Consik)

component yii2 websocket ratchet