Skip to content

WebSocket 协议

目前 Workerman 的 WebSocke 协议版本为 13

WebSocket protocol 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信。

WebSocket 与 TCP 关系

WebSocket 和 HTTP 一样是一种应用层协议,都是基于 TCP 传输的,WebSocket 本身和 Socket 并没有多大关系,更不能等同。

WebSocket 协议握手

WebSocket 协议有一个握手的过程,握手时浏览器和服务端是以 HTTP 协议通信的,在 Workerman 中可以这样介入到握手过程。

当 workerman <= 4.1 时

php
<?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
<?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 协议默认只能传输 utf8 文本,如果要传输二进制数据,请阅读以下部分。

websocket 协议中在协议头中使用一个标记位来标记传输的是二进制数据还是 utf8 文本数据,浏览器会验证标记和传输的内容类型是否符合,如果不符合则会报错断开连接。

所以服务端发送数据的时候需要根据传输的数据类型设置这个标记位,在 Workerman 中如果是普通 utf8 文本,则需要设置(默认就是此值,一般不用再手动设置)

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

如果是二进制数据,则需要设置

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

注意:如果没设置 $connection->websocketType,则 $connection->websocketType 默认为 BINARY_TYPE_BLOB(也就是 utf8 文本类型)。一般应用传输的都是 utf8 文本,例如传输的是 json 数据,所以不用手动设置 $connection->websocketType。只有在传输二进制数据时(例如图片数据、protobuffer 数据等)才要设置此属性为 BINARY_TYPE_ARRAYBUFFER。

把 workerman 作为 Websocket 客户端

可以利用 AsyncTcpConnection 类配合 ws 协议让 workerman 作为 websocket 客户端连接远程 websocket 服务端,完成双向实时通讯。

基于 MIT 许可发布