Протокол WebSocket

В настоящее время версия протокола WebSocket в Workerman составляет 13.

Протокол WebSocket - это новый протокол HTML5. Он реализует двустороннюю связь между браузером и сервером.

Взаимосвязь WebSocket и TCP

WebSocket, подобно HTTP, является протоколом прикладного уровня, основанным на передаче данных по TCP. Сам WebSocket не имеет прямого отношения к сокетам, тем более не может быть равнозначен.

Рукопожатие по протоколу WebSocket

Протокол WebSocket предусматривает процесс рукопожатия, при котором браузер и сервер обмениваются данными по протоколу HTTP. В Workerman можно вмешаться в этот процесс следующим образом.

Если версия Workerman <= 4.1

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Workerman\Connection\TcpConnection;
use Workerman\Worker;

$ws = new Worker('websocket://0.0.0.0:8181');
$ws->onConnect = function($connection)
{
    $connection->onWebSocketConnect = function($connection , $httpBuffer)
    {
        // Здесь можно проверить, является ли источник подключения законным, и в случае неподходящего источника закрыть соединение
        // $_SERVER['HTTP_ORIGIN'] указывает на сайт, с которого было запрошено websocket-соединение
        if($_SERVER['HTTP_ORIGIN'] != 'https://www.workerman.net')
        {
            $connection->close();
        }
        // В onWebSocketConnect можно использовать $_GET и $_SERVER
        // var_dump($_GET, $_SERVER);
    };
};
Worker::runAll();

Если версия Workerman >= 5.0

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;

$worker = new Worker('websocket://0.0.0.0:12345');
$worker->onWebSocketConnect = function (TcpConnection $connection, Request $request) {
    if ($request->header('origin') != 'https://www.workerman.net') {
        $connection->close();
    }
    var_dump($request->get());
    var_dump($request->header());
};
Worker::runAll();

Передача двоичных данных по протоколу WebSocket

По умолчанию протокол WebSocket может передавать только текст в кодировке UTF-8. Если необходимо передавать двоичные данные, обратитесь к следующему разделу.

В протоколе WebSocket используется маркировка в заголовке протокола для обозначения типа передаваемых данных: текстовые данные в UTF-8 или двоичные данные. Браузер проверяет маркер и соответствие типа данных, и, в случае несоответствия, может разорвать соединение.

Поэтому при отправке данных с сервера необходимо установить эту маркировку в зависимости от типа передаваемых данных. В Workerman, если это обычный текст в UTF-8, установите (обычно это устанавливается по умолчанию и не требует дополнительной настройки)

use Workerman\Protocols\Websocket;
$connection->websocketType = Websocket::BINARY_TYPE_BLOB;

Если передаются двоичные данные, установите

use Workerman\Protocols\Websocket;
$connection->websocketType = Websocket::BINARY_TYPE_ARRAYBUFFER;

Обратите внимание: если не установить $connection->websocketType, то по умолчанию $connection->websocketType будет равно BINARY_TYPE_BLOB (т.е. текст в UTF-8). Обычно приложения передают текстовые данные, например, данные в формате JSON, поэтому не нужно устанавливать $connection->websocketType. Это свойство необходимо устанавливать только при передаче двоичных данных (например, изображений, данных в формате Protobuf и т.д.).

Использование Workerman в качестве клиента WebSocket

Можно использовать класс AsyncTcpConnection с протоколом ws, чтобы Workerman действовал в качестве клиента WebSocket, подключаясь к удаленному серверу WebSocket и обеспечивая двустороннюю реальном времени связь.