1

我有一个非常奇怪的问题。我有一个开放的 WebSocket,通信完美。我还有窗口的 onblur 和 onfocus 事件,它们通过所述连接通知服务器。但是,在这种情况下,我收到的字符串是非空终止的。否则,即使发送在那些相应的模糊/焦点事件上发送的相同字符串,通信也绝对无可挑剔。为什么会这样,如何解决?

这是一些代码:

$(document).ready(function(){

    initializeEverything();

    window.onblur = function(){ notifyFocusChange(false); };

    window.onfocus = function(){ notifyFocusChange(true); };

});

function notifyFocusChange(present){

    if(present){
        webSocket.send('presence:present');
    }else{
        webSocket.send('presence:absent');
    }

}

这是事件触发时我收到的非空终止字符串的示例:

presence:absentÏ┘ê÷/à°äJ÷ÝÿLÓ▓ùM÷Ýÿ[

编辑:有人建议这可能是服务器错误,所以这里是解码传入消息的代码:

private function decode($payload) {

    $length = ord($payload[1]) & 127;

    if ($length == 126) {
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    } elseif ($length == 127) {
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    } else {
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    }

    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i % 4];
    }

    return $text;

}

编辑:它只发生在 Chrome 中。我在 Firefox 上检查了它,它使用相同的 WebSocket 协议,在那里一切正常。

4

1 回答 1

2

onblur 和 onfocus 事件可能会快速连续发生几次。这意味着 websocket.send 调用也被快速连续多次快速调用。

如果多个发送调用发生得足够近,那么您很可能会在服务器的一次读取中收到多个帧,我相信这就是您所看到的。换句话说,有效载荷中的“垃圾”实际上是一个或多个后续 WebSocket 帧。

您可以手动复制问题,在同一个 Javascript 上下文中执行两次单独的发送:

function do_test () {
    ws.send("data1");
    ws.send("data2");
}

这将发送两个足够接近的 WebSocket 帧,服务器可能会从套接字一次读取它们。

为了正确处理帧,您必须解析有效负载长度字段,并且只读取/取消屏蔽指定数量的有效负载数据。剩下的任何东西都需要排队作为新帧的开始。

此外,从套接字读取的一次读取不仅可以返回多个 Websocket 帧,而且您不能依赖作为整个帧读取的帧:您可能在一次读取中读取一半帧,在下一帧读取另一半帧。换句话说,第一次从套接字读取时,您可能会得到 3 个完整的 websocket 帧加上第 4 帧的 1 个字节,然后在下一次从套接字读取时,您会得到第 4 帧的其余部分。

这通常可以这样总结:WebSockets 是基于消息的传输协议,而 TCP 套接字是流式协议。由于 WebSockets 在 TCP 上分层,这意味着 WebSocket 服务器(和客户端)必须进行转换以将整个消息呈现给应用程序,即使底层传输不是基于消息的。

于 2012-06-26T17:17:41.173 回答