WebSocket TCP packets clumping together?

2019-01-15 13:04发布

Concerning JavaScript & PHP WebSocket TCP packet clumping, with example below.

For some reason, when sending packets quickly on my VPS, or accessing my localhost through a domain pointing at my IP address, multiple packets will clump together. I am trying to stream, for this example, 20 (@100byte) packets per second. On the servers end, they ARE indeed being sent out at a steady rate, exactly every 50ms, making 20 per second. However, when they get to the client, the client only processes new messages about every 1/4th of a second. Causing new packets only to be received at a rate of 4 per second or so...

What is causing this clumping of packets together? This problem does not occur when everything through localhost. What's weirder is that it streams smoothly on iPhone's iOS Mobile Safari, with no problem at all. BUT, it doesn't work at all on PC Safari, (because I haven't set this up to work correctly with the old Hixie-76 WebSocket format, I'm assuming Mobile Safari is already using the newer RFC 6455 or newer JavaScript compiler) I have tried multiple hosting companies, with the exact same results each time.

See the example below, hosted on InMotion's VPS: http://www.hovel.me/script/serverControl.php

(Click [Connect] on the left, then [View Game] on the right).

The current packet received will jump about 5 every time, as each 5 packets are received at once, every 1/4th of a second. However, I've seen examples that can send a constant, quick stream of packets. What causes this clumping together / packets to wait for each other?

EDIT: This HAS to be something to do with Nagle's algorithm, which collects & sends small packets together? I'll work towards trying to bypass this in PHP. Even with this TCP_NODELAY set in PHP, the problem still stands. Why it works on an iPhone but not a PC is still throwing me off...
EDIT: Setting TCPNoDelay and TcpAckFrequency to 1 in the registry fixes this, but I can't expect every user to do that. There must be a client-side, bread & butter JavaScript way.

How can I have functionality replicating node.js' "socket.setNoDelay(true)", without using node.js?

2条回答
仙女界的扛把子
2楼-- · 2019-01-15 13:44

In the end, the client not recognizing the Nagle's algorithm being disabled, along with it's acknowledge frequency still being set at around 200ms, was causing the intermediate network to hold the following packets in a buffer. Manually sending out an acknowledgement message to the server, every single time the client receives a message, will cause the network to immediately "wake-up" and continue to process the next packets, as opposed to holding them in a buffer.

For Example:

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

This temporary solution works, however this will nearly double bandwidth usage, among other network problems. Until I can get the WebSocket on the clients end to correctly not 'standby' for server ack, and the network to push through messages immediately, this gets the packets through quicker without the buffer corking problem.

查看更多
Deceive 欺骗
3楼-- · 2019-01-15 13:48

That's TCP. It is helping you by economizing on IP packets. Part of it is due to the Nagle algorithm but part of it may also be caused by the intermediate network.

查看更多
登录 后发表回答