我有一个非常奇怪的问题。我有一个开放的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协议,一切都很好。
答案 0 :(得分: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服务器(以及客户端)必须进行转换以将整个消息呈现给应用程序,即使底层传输不是基于消息的。