Protocolo WebSocket

Actualmente, la versión del protocolo WebSocket de Workerman es 13.

El protocolo WebSocket es un nuevo protocolo de HTML5. Permite la comunicación bidireccional entre el navegador y el servidor.

Relación entre WebSocket y TCP

Al igual que HTTP, WebSocket es un protocolo de aplicación, y ambos se basan en la transmisión TCP. WebSocket en sí no tiene mucha relación con Socket, y no se pueden considerar equivalentes.

Proceso de handshake del protocolo WebSocket

El protocolo WebSocket tiene un proceso de handshake, en el cual el navegador y el servidor se comunican a través del protocolo HTTP. En Workerman, se puede intervenir en el proceso de handshake de la siguiente manera.

Cuando 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)
    {
        // Aquí se puede verificar si la conexión es válida; si no lo es, se cierra la conexión
        // $_SERVER['HTTP_ORIGIN'] indica desde qué sitio se inició la conexión websocket
        if($_SERVER['HTTP_ORIGIN'] != 'https://www.workerman.net')
        {
            $connection->close();
        }
        // En onWebSocketConnect, $_GET y $_SERVER son accesibles
        // var_dump($_GET, $_SERVER);
    };
};
Worker::runAll();

Cuando 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();

Transmisión de datos binarios con el protocolo WebSocket

El protocolo websocket, por defecto, solo puede transmitir texto en utf8. Si se desea transmitir datos binarios, se debe leer la siguiente sección.

En el protocolo websocket, se utiliza un bit de marcador en el encabezado del protocolo para señalar si se están transmitiendo datos binarios o texto en utf8. El navegador validará si el marcador y el tipo de contenido transmitido coinciden; si no coinciden, se producirá un error y se cerrará la conexión.

Por lo tanto, al enviar datos desde el servidor, es necesario ajustar este bit de marcador según el tipo de datos a transmitir. En Workerman, si se trata de texto utf8 común, se debe establecer (este es el valor por defecto, generalmente no es necesario configurarlo manualmente)

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

Si se trata de datos binarios, se debe establecer

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

Nota: Si no se establece $connection->websocketType, el valor por defecto de $connection->websocketType será BINARY_TYPE_BLOB (es decir, tipo de texto utf8). Generalmente, las aplicaciones transmiten texto utf8, como datos en formato json, por lo que no es necesario configurar manualmente $connection->websocketType. Este atributo solo debe establecerse en BINARY_TYPE_ARRAYBUFFER cuando se transmiten datos binarios (por ejemplo, datos de imágenes, datos de protobuffer, etc.).

Usando Workerman como cliente WebSocket

Se puede utilizar la clase AsyncTcpConnection junto con el protocolo ws para permitir que Workerman actúe como un cliente websocket y se conecte a un servidor websocket remoto, completando la comunicación en tiempo real bidireccional.