WebSocket TCP数据包聚合在一起了?

11

关于JavaScript和PHP WebSocket的TCP数据包聚合问题,以下是示例。

由于某些原因,在我的VPS上快速发送数据包或通过指向我的IP地址的域访问本地主机时,多个数据包会聚集在一起。例如,我正在尝试每秒发送20个(@100byte)数据包进行流媒体传输。在服务器端,它们确实以稳定的速率发送出去,每50毫秒精确地发送20个数据包。 然而,当它们到达客户端时,客户端仅会每1/4秒处理新消息。这导致每秒只能接收大约4个新的数据包...

是什么导致数据包聚合在一起?当一切都在本地主机上运行时,此问题不会发生。更奇怪的是,它在iPhone的iOS移动Safari上平稳运行,没有任何问题。但是,在PC上的Safari中完全无法工作(因为我还没有正确设置它与旧的Hixie-76 WebSocket格式配合使用,我认为移动Safari已经使用了更新的RFC 6455或更新的JavaScript编译器),我尝试过多个托管公司,每次都得到完全相同的结果。

请参见以下示例,托管在InMotion的VPS上: http://www.hovel.me/script/serverControl.php

(单击左侧的[连接],然后单击右侧的[查看游戏])。

当前接收到的数据包将每次跳动大约5个,因为每1/4秒都会接收到5个数据包。但是,我看过一些可以发送连续快速流数据包的示例。 是什么导致这些数据包聚合在一起 / 等待彼此?

编辑: 这必须与Nagle算法有关,该算法收集并发送小数据包吗?我将尝试绕过PHP中的此问题。

即使在 PHP 中设置了 TCP_NODELAY,问题仍然存在。为什么 iPhone 上可以工作但 PC 上不行,这仍然让我感到困惑...
编辑: 在注册表中将 TCPNoDelay 和 TcpAckFrequency 设置为 1 可以解决此问题,但我不能指望每个用户都这样做。必须有一种基于客户端 JavaScript 的方法来解决此问题。

如何实现类似 node.js 的 "socket.setNoDelay(true)" 的功能,而不使用 node.js?

2个回答

5
最终,客户端没有意识到Nagle算法已被禁用,同时确认频率仍然设置在约200ms左右,这导致中间网络将以下数据包保留在缓冲区中。每次客户端接收到消息时手动向服务器发送确认消息,将立即使网络“唤醒”,并继续处理下一个数据包,而不是将其保留在缓冲区中。
例如:
conn = new WebSocket(url);
conn.onmessage = function(evt){
    Server.send('ACKNOWLEDGE BYTES'); // Send ACK to server immediately
    dispatch('message', evt.data); //Do regular event procedures
};

这个临时解决方案虽然可行,但是会 将带宽使用量增加近一倍,并引起其他网络问题。在我能够确保客户端的WebSocket正确地不会等待服务器的确认,并使网络立即传递消息之前,这种方法可以更快地传递数据包,避免缓冲堵塞的问题。

4

这是TCP。它通过节省IP数据包来帮助你。其中一部分原因是由于Nagle算法,但另一部分可能是由于中间网络造成的。


这是有道理的,但对于任何实时流传输都不适用,而且WebSocket目前不支持UDP,所以我暂时被困在这里。我知道有一个解决方法,但是通过PHP设置TCP_NODELAY(关闭Nagle算法)还没有解决我的问题。感谢您的帮助。 - TheWandererLee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接