PHP Websocket接收不完整的数据

时间:2017-01-21 11:31:22

标签: php websocket

我有以下代码来接收带有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获取完整数据的任何建议。谢谢你的帮助。

1 个答案:

答案 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;
}

}