3

我有 JavaScript 通过 WebSocket 连接在窗口上发送鼠标的坐标。

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

然后,我的后端 PHP 只是简单地监听这些坐标并将光标的位置发送给所有连接的人。

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

JavaScript 获取这些数字并根据这一点移动一个红色方块。

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

最终产品如下所示:

现在的问题是它非常滞后,但我找到了解决这个问题的方法。我为 JavaScript 添加了一个间隔——它每 50 毫秒发送一次填充数据。

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

令人惊讶的是,更改使它变得更加顺畅:

我注意到左侧(鼠标移动的地方)总是很平滑,我猜是因为左边的窗口总是发送数据,所以连接保持更平滑,而右边的窗口只有接收数据。

我试过了:

$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));

输出是int(-1),而且似乎 Nagle 的算法仍然存在于我的应用程序中。

有点相关,设置 TCP_NODELAY 会影响套接字两端的行为吗?,这可能是JavaScript故意延迟数据包的问题?


  • 为什么发送东西会使事情变得更顺畅?
  • 有没有办法可以加快速度,而不必发送无用的数据?
4

2 回答 2

4

您的问题与Nagle 算法有关:小数据包正在相互等待。

使用socket_set_option()禁用此设置 TCP_NODELAY 选项

关于您的编辑,您是绝对正确的。客户端是这里的问题,因为尽管您可以在浏览器中使用 javascript,但例如,Windows 系统确实有一个注册表设置,默认情况下在 tcp 上启用 Nagle。

于 2013-10-24T08:06:23.163 回答
0

不幸的是,这是一个客户端问题。

使用注册表编辑器(Start Orb -> Run -> regedit),我们可以启用 TCPNoDelay 以及设置 TcpAckFrequency。

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

此外,我还没有发现使用上下文更改 SOCK_STREAM 上的 TCP_NODELAY 是可能的或相关的。

在当前情况下,我刚刚决定确认(ACK)服务器发送的每个数据包。我知道这会牺牲带宽来换取延迟。

webSocket.onmessage = function(evt) {
    webSocket.send(''); //empty, but still includes headers
    dispatch(evt);
}
于 2013-10-25T05:38:18.810 回答