我有一个javascript websocket客户端和一个php websocket服务器。当我通过循环向服务器发送大量数据时,服务器窗口中会出现奇怪的字符。
我发送:
setInterval(function() {
for (var i=1; i<=5; i++) {
WS.send("0");
}
}, 1000);
在服务器窗口中:
Received [1]: 0╩┤&ψ╙]▬)╩Zόrcj
Received [1]: 0
Received [1]: 0≤↓ [☺ψ╧
Received [1]: 0¶╞0UoL
§╧q←%ved [1]: 0Τ
Received [1]: 0b:Ρ"6Τι
Received [1]: 0
Received [1]: 0
Received [1]: 0&Ρ┼→↑αΫ
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0╦►╬┘Τ7■
Received [1]: 0SΖ╥m╬'έ
Received [1]: 0
Received [1]: 0,!☼┘L╡?
Received [1]: 0L│%☼ΪH§
Received [1]: 0
Received [1]: 0▀μpp┤A@
Received [1]: 0V[A√╚ύq
当我发送频率较低的数据时,一切都很好
我发送:
setInterval(function() {
WS.send("0");
}, 1000);
并在服务器窗口中:
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0
Received [1]: 0
为什么会这样?这是正常的吗?
用于取消屏蔽数据的函数:
function unmask($data) {
$length = ord($data[1]) & 127;
if($length == 126) {$masks = substr($data, 4, 4); $data = substr($data, 8);}
elseif($length == 127) {$masks = substr($data, 10, 4); $data = substr($data, 14);}
else {$masks = substr($data, 2, 4); $data = substr($data, 6);}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {$text .= $data[$i] ^ $masks[$i%4];}
return $text;
}
我收到的消息是:
while(socket_recv($client, $buffer, 2048, 0) >= 1) {
$msg = unmask($buffer);
echo "$msg\n";
}
答案 0 :(得分:2)
由于Nagle's Algorithm,您的数据包中会出现多个WebSocket帧。您发送小消息的速度非常快,以便最大限度地减少网络拥塞,客户端会保留数据,直到从服务器获得确认,或者直到发生合理的超时为止。
要解决此问题,您只需关闭$length
个字节数,然后对剩余数据运行unmask()
函数。
您的代码也容易受到超大WebSocket帧在不同数据包之间分配的影响;尝试在邮件中发送超过64KB的数据,看看会发生什么。 (您可以降低并看到类似的结果;以太网的MTU为1500字节,但TCP本身的MTU为65536字节,因此当您发送超过64K时,您将始终看到碎片的影响。)
在我的服务器中,我为每个连接的用户提供了一个缓冲区,直到我有一个完整的WebSocket框架来处理碎片,我只从该缓冲区的前面拉出$header_length + $message_length
个值的数据一次,如果该缓冲区中有多个帧。