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回調。

相關文章
相關標籤/搜索