【问题标题】:PHP websocket | strange characters when sending data with high frequencyPHP websocket |高频发送数据时出现奇怪的字符
【发布时间】:2015-09-07 22:10:13
【问题描述】:

我有一个 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";
}

【问题讨论】:

  • 我的websocket服务器是用php语言写的
  • 我的意思是,你能给我们看一些代码吗?它几乎可能是任何原因造成的。
  • Nagle 算法:en.wikipedia.org/wiki/Nagle%27s_algorithm 。您在单个 TCP 数据包中获得了多个 WS 帧。

标签: php websocket character


【解决方案1】:

由于Nagle's Algorithm,您的数据包中有多个 WebSocket 帧。您发送小消息的速度如此之快,以至于为了最大限度地减少网络拥塞,客户端会一直保留数据,直到它从服务器得到确认,或者直到发生合理的超时。

要解决这个问题,您只需去掉$length 的字节数,然后对剩余数据运行unmask() 函数。

您的代码也容易受到在不同数据包中拆分过大的 WebSocket 帧的影响;尝试在消息中发送超过 64KB 的数据,看看会发生什么。 (您可以再往下走,看到类似的结果;以太网的 MTU 为 1500 字节,但 TCP 本身的 MTU 为 65536 字节,因此当您发送超过 64K 时,您将始终看到碎片的影响。)

在我的服务器中,我为每个已连接的用户设置了一个缓冲区,该缓冲区被填满,直到我有一个完整的 WebSocket 帧来处理碎片,并且我只在该缓冲区的前面提取了 $header_length + $message_length 的数据时间,以防该缓冲区中有多个帧。

【讨论】:

  • 谢谢你,我的朋友。因为我不是那么先进,你能写“unmask”函数吗?我会更容易研究这个,因为我不理解这些东西 100%
  • 例如,我怎样才能得到 $length 值来去掉这些字节
  • “如果你给一个人生火,你会温暖他一夜。如果你让一个人着火,你会温暖他的余生。” -- 不。WebSockets 实现起来很简单,但它不是 PHP 开发人员的“初学者”主题。如果您需要一些只适用于您获得报酬的工作的东西,那就去找一个开源服务器。如果您为了学习而学习,请记住失败是学习的重要组成部分,最终的成功会变得更有价值。
  • 话虽如此,消息的长度包含在帧中。你的 unmask 函数已经把这个值拉出来了。
  • @marirena 而且,讨论如何创建 WebSocket 服务器的基本细节超出了任何一个问题和本网站的范围。如果/当您再次陷入困境时,请随时提出更多问题,或加入聊天室。 (标记这个,因为我终于得到了我想说的所有内容。)
猜你喜欢
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 2021-01-16
  • 2018-05-14
  • 1970-01-01
相关资源
最近更新 更多