Join 4,000+ others and never miss out on new tips, tutorials, and more.
4.x is outdated, please check the latest version 25.x
Latest version:
pecl install openswoole-25.2.0
<?php Swoole\WebSocket\Server->on('Handshake', callable $callback)
The event name to set a callback for
Handshake callback function, the callback function returns handshake result status.
If success, it returns true, otherwise it returns false
This function is optional to create a WebSocket server.
This function is executed when a WebSocket connection is established and going into the handshake stage.
The built-in default handshake protocol is Sec-WebSocket-Version: 13. You can override the default handshake protocol by implementing this function, otherwise you can leave out this event.
If you set your own handshake function, the server will not call the Open event, your application needs to handle this. You can use $server->defer() to replicate Open event logic (see example).
When implementing a custom handshake you must call $response->status(101) and $response->end() in order to complete the handshake otherwise it will fail.
<?php
use Swoole\WebSocket\Server;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
$server = new Server("127.0.0.1", 9501);
$server->on("Start", function(Server $server)
{
echo "Swoole WebSocket Server started at http://127.0.0.1:9501\n";
});
$server->on('handshake', function (Swoole\HTTP\Request $request, Swoole\HTTP\Response $response)
{
$secWebSocketKey = $request->header['sec-websocket-key'];
$patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
// At this stage if the socket request does not meet custom requirements, you can ->end() it here and return false...
// Websocket handshake connection algorithm verification
if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey)))
{
$response->end();
return false;
}
echo $request->header['sec-websocket-key'];
$key = base64_encode(sha1($request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$headers = [
'Upgrade' => 'websocket',
'Connection' => 'Upgrade',
'Sec-WebSocket-Accept' => $key,
'Sec-WebSocket-Version' => '13',
];
// WebSocket connection to 'ws://127.0.0.1:9501/'
// Failed: Error during WebSocket handshake:
// Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket
if(isset($request->header['sec-websocket-protocol']))
{
$headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
}
foreach($headers as $key => $val)
{
$response->header($key, $val);
}
$response->status(101);
$response->end();
echo "connected!" . PHP_EOL;
return true;
});
$server->on('Open', function(Server $server, Swoole\Http\Request $request)
{
echo "connection open: {$request->fd}\n";
$server->tick(1000, function() use ($server, $request)
{
$server->push($request->fd, json_encode(["hello", time()]));
});
});
$server->on('Message', function(Server $server, Frame $frame)
{
echo "received message: {$frame->data}\n";
$server->push($frame->fd, json_encode(["hello", time()]));
});
$server->on('Close', function(Server $server, int $fd)
{
echo "connection close: {$fd}\n";
});
$server->start();
By implementing your own HandShake algorithm handles the connection establishment and validation, the Swoole server won't trigger the Open event. Instead you need to implement this logic, this can be easily done with $server->defer().
<?php
$server->on('Handshake', function (\Swoole\Http\Request $request, \Swoole\Http\Response $response) use ($server) {
// Handshake verification completed, validate request...
$response->status(101);
$response->end();
$fd = $request->fd;
// Same logic as the server Open event, will not block
$server->defer(function() use ($fd, $server)
{
echo "Client connected\n";
$server->push($fd, "hello, welcome\n");
});
});