MyTetra Share
Делитесь знаниями!
consik/yii2-websocket
Время создания: 22.05.2018 18:11
Текстовые метки: php packagist websocket yii2
Раздел: WebSocket

Used Ratchet


Installation

The preferred way to install this extension is through composer.


Either run


composer require consik/yii2-websocket

or add


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

WebSocketServer class description

Properties

int $port = 8080 - Port number for websocket server

bool $closeConnectionOnError = true - Close connection or not when error occurs with it

bool $runClientCommands = true - Check client's messages for commands or not

null|IoServer $server = null - IOServer object

null|\SplObjectStorage $clients = null - Storage of connected clients

Methods

Events

EVENT_WEBSOCKET_OPEN

Class yii\base\Event - Triggered when binding is successfully completed


EVENT_WEBSOCKET_CLOSE

Class yii\base\Event - Triggered when socket listening is closed


EVENT_WEBSOCKET_OPEN_ERROR

Class events\ExceptionEvent - Triggered when throwed Exception on binding socket


EVENT_CLIENT_CONNECTED

Class events\WSClientEvent - Triggered when client connected to the server


EVENT_CLIENT_DISCONNECTED

Class events\WSClientEvent - Triggered when client close connection with server


EVENT_CLIENT_ERROR

Class events\WSClientErrorEvent - Triggered when an error occurs on a Connection


EVENT_CLIENT_MESSAGE

Class events\WSClientMessageEvent - Triggered when message recieved from client


EVENT_CLIENT_RUN_COMMAND

Class events\WSClientCommandEvent - Triggered when controller starts user's command


EVENT_CLIENT_END_COMMAND

Class events\WSClientCommandEvent - Triggered when controller finished user's command


Examples


Simple echo server


Create your server class based on WebSocketServer. For example daemons\EchoServer.php:


<?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:


<?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:


php yii server/start


Now let's check our server via js connection:


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:


Connection established!


Hey!


Response:Hey!


Handle server starting success and error events


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


Create yii2 console controller for starting server:


<?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:


php yii server/start


Server console result must be:


Error opening port 80


Server started at port 81


Recieving client commands


You can implement methods that will be runned after some of user messages automatically;


Server class daemons\CommandsServer.php:


<?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


Check connection and command working by js script:


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:


ping


Response:Pong


Chat example


In the end let's make simple chat with sending messages and function to change username;


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


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>

<div id="chat" style="width:400px; height: 250px; overflow: scroll;"></div>

Message:<br />

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

<div id="response" style="color:#D00"></div>


JS code for chat with jQuery:

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>

<script>

$(function() {

var chat = new WebSocket('ws://localhost:8080');

chat.onmessage = function(e) {

$('#response').text('');


var response = JSON.parse(e.data);

if (response.type && response.type == 'chat') {

$('#chat').append('<div><b>' + response.from + '</b>: ' + response.message + '</div>');

$('#chat').scrollTop = $('#chat').height;

} else if (response.message) {

$('#response').text(response.message);

}

};

chat.onopen = function(e) {

$('#response').text("Connection established! Please, set your username.");

};

$('#btnSend').click(function() {

if ($('#message').val()) {

chat.send( JSON.stringify({'action' : 'chat', 'message' : $('#message').val()}) );

} else {

alert('Enter the message')

}

})


$('#btnSetUsername').click(function() {

if ($('#username').val()) {

chat.send( JSON.stringify({'action' : 'setName', 'name' : $('#username').val()}) );

} else {

alert('Enter username')

}

})

})

</script>


Enjoy ;)


Other


Starting yii2 console application as daemon using nohup


nohup php yii _ControllerName_/_ActionName_ &

Так же в этом разделе:
 
MyTetra Share v.0.53
Яндекс индекс цитирования