3

I have JavaScript sending the coordinates of my mouse over the window via a WebSocket connection.

var webSocket = new WebSocket('ws:// ...');
$(window).mousemove(function (evt) {
    webSocket.send(evt.pageX + ' ' + evt.pageY);
});

Then, PHP, my backend, is simply listening for these coordinates and sending to everyone who is connected the position of the cursor.

//whenever someone sends coordinates, all users connected will be notified
foreach ($webSocket->getUsers() as $user)
    $user->send($xpos . ' ' . $ypos);

JavaScript gets these numbers and moves a red square based on this point.

//when PHP notifies a user, the square is updated in position
$('.square').css({
    left: xpos,
    top: ypos
});

The end product looks like this:

Now the issue is that it's very laggy, but I've found a way to combat this. I've added a interval for the JavaScript -- which just sends filler data every 50 milliseconds.

setInterval(function() {
    webSocket.send('filler data');
}, 50);

Surprisingly, the change made it much smoother:

I've noticed how the left-side (where the mouse is being moved from), is always smooth, and I'm guessing that because the left window is always sending data, the connection is being kept smoother whereas the right window is only receiving data.

I've tried:

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, TCP_NODELAY, 1);
var_dump(socket_get_option($socket, SOL_SOCKET, TCP_NODELAY));

The output was int(-1), and it seems that Nagle's algorithm is still present in my application.

Somewhat related, Does setting TCP_NODELAY affect the behaviour of both ends of the socket?, this might be the issue of JavaScript purposely delaying the packets?


  • Why does sending something make it smoother?
  • Is there a way I can speed this up, without having to send useless data?
Community
  • 1
  • 1
Dave Chen
  • 10,887
  • 8
  • 39
  • 67
  • I think the problem is when you send while you move your mouse it sends more data perhaps 1000 mouse events in a sec which makes 1000Hz, but 50ms limits this to 20Hz a huge data transfer difference, TCP_NODELAY is related with the OS buffering, if you set it on the server side it will effect the latency for the push(of data) from server to brower – user818117 Sep 02 '21 at 17:47

2 Answers2

4

Your issue has to do with Nagle's Algorithm: Small packets of data are waiting for each other.

to disable this set TCP_NODELAY option using socket_set_option()

Regarding your edit, you are absolutely right. The client side is the problem here, because, although you can use javascript in your browser, windows systems, for example, do have a registry setting which by default enable Nagle on tcp.

TheCarver
  • 19,391
  • 25
  • 99
  • 149
Udan
  • 5,429
  • 2
  • 28
  • 34
0

Unfortunately this is a client-sided issue.

Using the registry editor (Start Orb -> Run -> regedit), we can enable TCPNoDelay as well set the TcpAckFrequency.

Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\

Furthermore, I have not found it possible or relevant to change TCP_NODELAY on SOCK_STREAM with contexts.

In the current situation, I have just decided to acknowledge (ACK) every packet that the server sends. I know this will be sacrificing bandwidth for latency.

webSocket.onmessage = function(evt) {
    webSocket.send(''); //empty, but still includes headers
    dispatch(evt);
}
Dave Chen
  • 10,887
  • 8
  • 39
  • 67