Swoole WebSocket Server

The following PHP codes shows how to write a simple WebSocket server. The WebSocket server sends the client a message when the WebSocket connection is established.

The Swoole\WebSocket\Server class inherits from the class swoole_server.

Example Code

<?php

$server = new Swoole\WebSocket\Server("0.0.0.0", 9502);

$server->on("start", function (Swoole\WebSocket\Server $server) {
    echo "Swoole WebSocket Server is started at http://127.0.0.1:9502\n";
});

$server->on('open', function(Swoole\WebSocket\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(Swoole\WebSocket\Server $server, Swoole\WebSocket\Frame $frame) {
    echo "received message: {$frame->data}\n";
    $server->push($frame->fd, json_encode(["hello", time()]));
});

$server->on('close', function(Swoole\WebSocket\Server $server, int $fd) {
    echo "connection close: {$fd}\n";
});

$server->start();

Events and Callback Functions

The class Swoole\WebSocket\Server inherits from the class Swoole\Server. It adds three new events excpet for the event of class Swoole\Server and class Swoole\HTTP\Server.

onHandShake (Optional)

This event happens when the websocket connection start the handshake process. The Swoole\WebSocket\Server has built-in callback function registered for event handshake. But you can also choose to custom your callback function for event handshake.

Example

<?php
function onHandShake(Swoole\HTTP\Request $request, Swoole\HTTP\Response $response)
  • If the return of function is true, the handshake is successful.

The callback function for event handshake is optional.

If the callback function for event handshake has been customed, the event open would not be triggered.

The built-in protocol of handshake is Sec-WebSocket-Version: 13, it needs to implemen t the process of handshake when the browser is in low-version.

Example Code

<?php
$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]==$#';

    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:9502/'
    // 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;
});

onOpen

The event open happens when the websocket server and client has created the connection and finished the handshake. And the callback function registered for event open will be called.

Example

<?php
function onOpen(Swoole\WebSocket\Server $server, Swoole\HTTP\Request $req)
  • $req the object of http request, it contains the information of client

In the callback function for event open, you can push message to client and close the connection.

The callback function for event open is optional.

Events and Callback Functions

onMessage

The event message happens when the swoole websocket server receives the data frame from the client.

Example

<?php
function onMessage(Swoole\WebSocket\Server $server, Swoole\WebSocket\Frame $frame)
  • $frame the object of class Swoole\WebSocket\Frame. It contains the infomation from the client

For swoole websocket server, it must set the callback function for the event message

The ping frame from the client will not trigger the event message and the swoole websocket server will respond pong automatically.

Swoole\WebSocket\Frame

The class Swoole\WebSocket\Frame has four properties:

  • $frame->fd the id number of client

  • $frame->data the data from the client. It can be text or binary data which can be distinguished by the value of $frame->opcode.

  • $frame->opcode the opcode type of websocket

  • $frame->finish if the data frame is complete.

OpCode and Data type
  • WEBSOCKET_OPCODE_TEXT = 0x1, text

  • WEBSOCKET_OPCODE_BINARY = 0x2, binary data

Method

The Swoole\WebSocket\Server class inherits from the class swoole_server. It has also its own method.

Swoole\WebSocket\Server->push

This method is to push the message to the client. The max length of message is 2M.

<?php
bool Swoole\WebSocket\Server->push(int $fd, string $data, int $opcode = 1, bool $finish = true);
  • $fd the id number of client. If the client isn't websocket client, the push will fail.

  • $data the message to send

  • $opcode the format of message to send. The default is text. If you want to send binary data, the value of this parameter should be WEBSOCKET_OPCODE_BINARY

  • If the push of message succeeds, the return is true otherwise false

Predefined Contants
Types of websocket data frame
  • WEBSOCKET_OPCODE_TEXT = 0x1, utf8 text data

  • WEBSOCKET_OPCODE_BINARY = 0x2, binary data

  • WEBSOCKET_OPCODE_PING = 0x9, ping data

Status of websocket connection
  • WEBSOCKET_STATUS_CONNECTION = 1, connection created and wait for handshake
  • WEBSOCKET_STATUS_HANDSHAKE = 2, in the process of handshake
  • WEBSOCKET_STATUS_FRAME = 3, handshake finished and wait for tranforming message

If the swoole_websocket_server has been setted the callback function of event request, it can be used as Http server.

If the swoole_websocket_server hasn't been setted the callback function of event request and received http request, it would repond http 400 error.