【问题标题】:Disabling Nagle's Algorithm Client Side/JavaScript禁用 Nagle 的算法客户端/JavaScript
【发布时间】:2016-02-08 22:55:07
【问题描述】:

客户端是否也需要禁用 Nagle 算法?如果是这种情况,我还没有找到单独通过 JavaScript 禁用 Nagle 算法的方法。

我正在尝试通过 websocket 从托管在 Raspbian OS 上的 PHP CLI 服务器传输数据(也托管在 Windows 7 和 Ubuntu 上,结果相同)。此服务器已成功创建套接字并接受多个连接,并已设置 TCP_NODELAY 标志(仅使用 socket_get_option 验证)。

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
socket_set_option($sock, SOL_SOCKET, TCP_NODELAY, 1);

在大多数平台上,无论是否设置了此 TCP_NODELAY 标志,数据都会流式传输而不会聚集。但是,在 Windows 7 Chrome 和 Firefox 上,数据以块的形式到达(有 0.2 秒的延迟)。在 Windows 8、Linux、iOS 和 Windows 7 的 Internet Explorer 11 上:我根本看不到这个问题

http://www.13willows.com/hovelme/script/serverControl.php 这是测试网站,单击“连接”,然后单击“查看游戏”,您应该会看到当前数据包每 50 毫秒从 1 稳步递增到 20。但是,在某些客户端上,它大约每 200 毫秒一次跳跃 4 次。

有什么想法可以阻止这种情况吗?使用 node.js / socket.io 会修复这样的问题,并且仍然允许我从用户的浏览器运行代码吗?

【问题讨论】:

    标签: javascript php node.js socket.io nagle


    【解决方案1】:

    至少 Chrome 似乎禁用了所有 WebSocket 套接字的 Nagle 算法:

    值得注意的是,Chrome 还在其所有 TCP 套接字上禁用了 Nagle 算法。

    但似乎应该在两侧启用 NODELAY 选项以保证低延迟:

    我们已经在所有平台上禁用了 Nagle,只使用了这种方法,但这并没有禁用延迟 ACK(或者至少它不会在 Windows 上,它肯定有可能在其他地方这样做)。

    source

    Chromium 源代码似乎证明了这一点(但我不是 Chromium 开发人员,所以我只是猜测,正如上面的一位评论员所说,在所有 TCP 套接字上调用了以下代码):

    void TCPSocketPosix::SetDefaultOptionsForClient() {
      DCHECK(socket_);
    
      // This mirrors the behaviour on Windows. See the comment in
      // tcp_socket_win.cc after searching for "NODELAY".
      // If SetTCPNoDelay fails, we don't care.
      SetTCPNoDelay(socket_->socket_fd(), true);
    
      // TCP keep alive wakes up the radio, which is expensive on mobile. Do not
      // enable it there. It's useful to prevent TCP middleboxes from timing out
      // connection mappings. Packets for timed out connection mappings at
      // middleboxes will either lead to:
      // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this
      // and retry. The HTTP network transaction code does this.
      // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP
      // stack retransmitting packets per TCP stack retransmission timeouts, which
      // are very high (on the order of seconds). Given the number of
      // retransmissions required before killing the connection, this can lead to
      // tens of seconds or even minutes of delay, depending on OS.
    #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
      const int kTCPKeepAliveSeconds = 45;
    
      SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds);
    #endif
    }
    

    link to source line

    另请参阅这个可能的解决方法 - https://stackoverflow.com/a/13406438/3167374

    【讨论】:

      猜你喜欢
      • 2014-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      相关资源
      最近更新 更多