在以前的版本中可能有這樣一種狀況,在 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
這樣的輸出並不能知道這個$fd
爲1
的鏈接是否爲 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
事件中正常結束則不會調用onClose
或onDisconnect
事件。
反之,若是不設置 onDisconnect
事件回調,非 WebSocket 請求或者在 onRequest
調用 $response->close()
方法,則都會調用onClose
回調。