2
头图

In the previous version, there may be such a situation, in the close event callback in the WebSocket server, it is impossible to distinguish whether the fd is a WebSocket connection, for example, the following code:

//创建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();

After starting the service, use the browser to 127.0.0.1:9501 , and the terminal will get the output:

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

Such output does not know $fd to 1 is a WebSocket connection. It is useless to directly use the $fd do some logical processing in the business code, and it may also happen that someone maliciously requests to occupy resources.

So familiar Swoole development of people will think of can be added to determine: Use getClientInfo method websocket_status value to get the WebSocket connection status

When the server is WebSocket\Server , getClientInfo will add additional websocket_status information, which has 4 corresponding states, namely

constantCorresponding valueDescription
WEBSOCKET_STATUS_CONNECTION1Connection enters waiting for handshake
WEBSOCKET_STATUS_HANDSHAKE2Shaking hands
WEBSOCKET_STATUS_ACTIVE3The handshake has been successful, waiting for the browser to send the data frame
WEBSOCKET_STATUS_CLOSING4The connection is in the process of closing handshake and will be closed soon

You can modify the onClose callback in the above code:

$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 can also set the onRequest callback, the same increase:

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

Restart the server, use the WebSocket client to request and close the request and the browser to request http://127.0.0.1:9501/?close=1 , and you will get this output:

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

Now starting from the v4.7.0 version, the onDisconnect event callback has been added, and the following code has been added:

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

Restart the server, you will get:

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

In this way, you can directly distinguish whether the connection is a WebSocket connection.

WebSocket\Server sets the onDisconnect event callback, non-WebSocket requests or calling the $response->close() onRequest will call back onDisconnect . However, if the onRequest event ends normally, the onClose or onDisconnect event will not be called.

Conversely, if you do not set the onDisconnect event callback, non-WebSocket request or call the $response->close() onRequest onClose callback will be called.


沈唁
1.9k 声望1.2k 粉丝