Swoole v4.7 版本新特性预览之 onDisconnect 事件回调

在以前的版本中可能有这样一种状况,在 WebSocket 服务器中没法在 close 事件回调中区分该 fd 是否为 WebSocket 链接,例如如下代码:php

//建立WebSocket Server对象,监听0.0.0.0:9501端口
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9501);

//监听WebSocket链接打开事件
$ws->on('Open', function ($ws, $request) {
    $ws->push($request->fd, "hello, welcome\n");
});

//监听WebSocket消息事件
$ws->on('Message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

//监听WebSocket链接关闭事件
$ws->on('Close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

启动服务后,使用浏览器对127.0.0.1:9501发起请求,终端会获得输出:web

client-1 is closed
[2021-05-24 16:58:08 *37715.1]  NOTICE  end (ERRNO 1005): session[1] is closed

这样的输出并不能知道这个$fd1的链接是否为 WebSocket 链接。若是业务代码中存在直接使用该$fd去作一些逻辑处理是无用的,也有可能会发生有人恶意请求致使占用资源。浏览器

那么熟悉 Swoole 开发的人就会想到能够增长判断:使用 getClientInfo 方法的websocket_status值来获取 WebSocket 链接状态bash

当服务器是 WebSocket\Server 时, getClientInfo 会额外增长websocket_status信息,它有对应的 4 种状态,分别为服务器

常量 对应值 说明
WEBSOCKET_STATUS_CONNECTION 1 链接进入等待握手
WEBSOCKET_STATUS_HANDSHAKE 2 正在握手
WEBSOCKET_STATUS_ACTIVE 3 已握手成功等待浏览器发送数据帧
WEBSOCKET_STATUS_CLOSING 4 链接正在进行关闭握手,即将关闭

能够修改上述代码中的 onClose 回调:websocket

$ws->on('Close', function ($ws, $fd) {
    $is_websocket = $ws->getClientInfo($fd)['websocket_status'];
    if ($is_websocket) {
        echo "client-{$fd} is closed, WebSocket status is {$is_websocket}\n";
    } else {
        echo "client-{$fd} is not a valid WebSocket connection\n";
    }
});

WebSocket\Server 还能够设置onRequest回调,同理增长:swoole

$ws->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) {
    if (isset($request->get['close'])) {
        $response->close();
    }
});

重启服务器,分别使用 WebSocket 客户端来请求后关闭和浏览器请求 http://127.0.0.1:9501/?close=1 后会获得这样的输出:session

client-1 is closed, WebSocket status is 3
client-2 is not a valid WebSocket connection

如今从 v4.7.0 版本开始,增长了 onDisconnect 事件回调,在上述代码中增长:socket

//监听WebSocket错误的链接关闭事件
$ws->on('Disconnect', function ($ws, $fd) {
    echo "client-{$fd} is Disconnect\n";
});

重启服务器,发起请求会获得:spa

client-1 is closed, WebSocket status is 3
client-2 is Disconnect

这样就能够直接来区分链接是否为 WebSocket 链接。

WebSocket\Server设置了 onDisconnect 事件回调,非 WebSocket 请求或者在 onRequest 调用 $response->close() 方法,都会回调onDisconnect。而在 onRequest 事件中正常结束则不会调用onCloseonDisconnect事件。

反之,若是不设置 onDisconnect 事件回调,非 WebSocket 请求或者在 onRequest 调用 $response->close() 方法,则都会调用onClose回调。

相关文章
相关标签/搜索