-
Notifications
You must be signed in to change notification settings - Fork 390
7. Websocket
This is a very important feature of this package. Generally in Laravel when you want to build a webscoket server, you have to rely on third party websocket server. The most common way is to use Pusher
or Socket.io
provided by NodeJS and with combination of Broadcasting
. There's no way to build a websocket server in Laravel.
Now with Swoole, it is possible and not difficult to integrate with Laravel. Nowadays when we talk about Websocket
, the majority choose Socket.io
to be their solution. The good news is this package is compatible with Socket.io
protocol(partially). That means in the brower or other clients you can use Socket.io
client directly.
These Socket.io
features are not implemented:
- namespace
- path
- long polling
- sid (sid interacts with server will be ignored)
- only supports
text
type data
After you run vendor:publish
, you can find websocket.php
in your routes folder. This is where you can register your websocket events. It looks pretty much like how you register a HTTP route in Laravel. You can register events with on
function, and it supports callback function or handler path.
<?php
use SwooleTW\Http\Websocket\Facades\Websocket;
/*
|--------------------------------------------------------------------------
| Websocket Routes
|--------------------------------------------------------------------------
|
| Here is where you can register websocket events for your application.
|
*/
Websocket::on('open', function ($websocket, $data) {
// in open callback, data will be illuminate request
$websocket->emit('message', 'welcome');
});
Websocket::on('disconnect', function ($websocket) {
//
});
Websocket::on('example', function ($websocket, $data) {
$websocket->emit('message', $data);
});
Websocket::on('test', 'ExampleController@method');
In callback functions, you can get $websocket
and $data
as parameters.
Parameter sequence doen't matter, but parameter names does.
Here's websocket's API:
function | Parameters | Description |
---|---|---|
on |
string $event, callable $callback |
Listen to a event name, and bind to handler |
broadcast | None | Set current message to broadcast |
to |
int string $value |
Assigned to specific fd, or specific room name |
toAll |
array $values |
Assigned to multiple fds or rooms |
join |
string $room |
Join current sender to a room |
joinAll |
array $rooms |
Join current sender to multiple rooms |
leave |
string $room |
Make current sender leave a specific room |
leaveAll |
array $rooms |
Make current sender leave multiple rooms |
emit |
string $event, mixed $data |
Emit an event with data |
close | None | Close current connection |
getSender | None | Get current sender's fd |
getIsBroadcast | None | Get if is briadcast now |
getTo | None | Get assigned fds and rooms |
reset |
boolean $force |
Reset isBroadcast , to and sender (if force is true) |
The usage of websocket refers to
Socket.io
, so they look a liitle bit similar.
<?php
use SwooleTW\Http\Websocket\Facades\Websocket;
// sending to sender-client only
Websocket::emit('message', 'this is a test');
// sending to all clients except sender
Websocket::broadcast()->emit('message', 'this is a test');
// sending to all clients in 'game' room(channel) except sender
Websocket::broadcast()->to('game')->emit('message', 'nice game');
// sending to all clients in 'game' including sender client
Websocket::to('game')->emit('message', 'enjoy the game');
// sending to individual socketid 1
Websocket::broadcast()->to(1)->emit('message', 'for your eyes only');
// join to subscribe the socket to a given channel (server-side):
Websocket::join('some room');
// leave to unsubscribe the socket to a given channel (server-side)
Websocket::leave('some room');
<?php
use SwooleTW\Http\Websocket\Facades\Room;
// get all fds in a 'game' room
Room::getClients('game');
// get all rooms of fd 1
Room::getRooms(1);
// add fd 1 to a 'game' room
Room::add(1, 'room');
// add fd 1 to 'game' and 'test' rooms
Room::addAll(1, ['game', 'test']);
// delete fd 1 from a 'game' room
Room::delete(1, 'room');
// delete fd 1 from 'game' and 'test' rooms
Room::deleteAll(1, ['game', 'test']);
Default handler uses Socket.io
, but you can still use your customized websocket protocol.
There are few classes you need to implement:
- Websocket Handler: Need to implement
HandlerContract
<?php
namespace SwooleTW\Http\Websocket;
use Illuminate\Http\Request;
use Swoole\Websocket\Frame;
interface HandlerContract
{
/**
* "onOpen" listener.
*
* @param int $fd
* @param \Illuminate\Http\Request $request
*/
public function onOpen($fd, Request $request);
/**
* "onMessage" listener.
* only triggered when event handler not found
*
* @param \Swoole\Websocket\Frame $frame
*/
public function onMessage(Frame $frame);
/**
* "onClose" listener.
*
* @param int $fd
* @param int $reactorId
*/
public function onClose($fd, $reactorId);
}
- Packet Parser: Need to extend
Parser
<?php
namespace SwooleTW\Http\Websocket\Foo;
use Swoole\Websocket\Frame;
use SwooleTW\Http\Websocket\Parser;
class FooParser extends Parser
{
/**
* Strategy classes need to implement handle method.
*/
protected $strategies = [
// optional
];
/**
* Encode output message for websocket push.
*
* @return mixed
*/
public function encode($event, $data)
{
// your logic
return $result;
}
/**
* Decode message from websocket client.
* Define and return payload here.
*
* @param \Swoole\Websocket\Frame $frame
* @return array
*/
public function decode(Frame $frame)
{
// your logic
return [
'event' => $yourParsedEventName,
'data' => $yourParsedData
];
}
}
And then configure them in swoole_websocket.php
'handler' => SwooleTW\Http\Websocket\SocketIO\WebsocketHandler::class,
'parser' => SwooleTW\Http\Websocket\SocketIO\SocketIOParser::class,