【问题标题】:PHP Websocket receiving incomplete dataPHP Websocket接收不完整的数据
【发布时间】:2017-01-24 01:59:45
【问题描述】:

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

【问题讨论】:

  • Sockets != WebSockets
  • 感谢错误代码为 0,但我想我没有得到不完整的数据,但数据是零散的。现在,我真的很纠结如何揭开碎片数据的面纱。我可以不加掩饰地获取第一帧,但无法屏蔽下一帧。

标签: php websocket


【解决方案1】:

这个问题的解决方法如下

问题:当使用 websocket 接收长字节的数据时,像socket_recv($socket,$buffer,5000,0); 这样的单次调用可能无法获得完整的数据,您需要再次调用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 的值,您需要在函数外部定义它并使其成为全局。

我在下面提供了新旧代码供您参考。我希望这是正确的解决方案,但请随时添加任何内容,或者让我知道我是否在任何地方出错。

我原来的 Unmask 函数:

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

}

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多