我有以下代码来接收带有websocket的数据。
$bytes=socket_recv($socket,$buffer2,1024,0);
$datarec=unmask($buffer2);
//process further
这有效,但很多时候我收到的信息不完整,我无法进一步处理数据。
我想出了以下解决方案。
基本上我保留数据长度的前10位数字,然后在使用javascript的socket.send发送之前,我在消息开头添加数据的长度。因此,如果我的消息是“你好这是一条消息”它变成“30:sizehello这是一条消息”我补偿了添加的“30:size”。
在php方面,我希望这样做
首先阅读10位数字。
$length=socket_recv($socket,$buffer2,1024,MSG_WAITALL);
然后使用类似
的内容$datarec=aocket_recv($socket,$buffer2,$length,MSG_WAITALL);
可悲的是,这不起作用,因为我无法读取和取消屏蔽第二次使用socket_recv收到的数据。
有关如何在不事先了解数据长度的情况下确保从websocket获取完整数据的任何建议。谢谢你的帮助。
答案 0 :(得分:1)
此问题的解决方法如下
问题:使用带有socket_recv($socket,$buffer,5000,0);
之类的websocket接收长字节数据时,您可能无法在单次调用中获得完整数据,并且需要再次调用socket_recv($socket,$buffer,5000,0);
。
例如,假设我们使用JS(socket.send)从浏览器向websocket发送了8000字节的数据。在服务器端,我们将使用socket_recv来获取消息。但我们可能只接收大约4000字节的数据,可能需要再次调用socket_recv来获取剩余的4000字节。
现在在我的原始代码中,我曾经在调用socket_recv来取消屏蔽数据后立即调用函数“unmask”。这适用于收到的第一组消息。但是对于下一组消息,“unmask”函数将尝试提取新的Mask并应用它。这是错误,因为消息是前一个消息的继续,并且Mask不会更改。解决方案是保持掩码不受第一条消息的影响,并检查下一条消息是否继续。这可以通过检查消息的第一位来完成。
$fin=ord($payload[0]) & 0x77;
如果$ fin为1,则消息是新消息,否则它是先前消息的延续。如果($ fin!= 1),您需要使用先前消息的掩码来取消屏蔽消息。不要忘记,因为您需要再次使用mask的值,您需要在函数外部定义它并使其全局化。
我在下面提供了新旧代码供您参考。我希望这是正确的解决方案,但如果我在任何地方出错,请随时添加任何内容或让我知道。
我的原始取消屏蔽功能:
function unmask($payload) {
$length = ord($payload[1]) & 127;
if($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
$firstcode=substr($payload, 1, 1);
}
elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
$firstcode=substr($payload, 1, 1);
}
else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
$firstcode=substr($payload, 1, 1);
}
$text = '';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
更新功能
function unmask($payload,$masks) {
global $masks;
$fin=ord($payload[0]) & 0x77;
if($fin!=1){
$data=substr($payload,0);
$text='';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}else{
$length = ord($payload[1]) & 127;
Echo "Mask functiion Payload Lenght".$length."\n";
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;
}
}