设置 TCP_QUICKACK 和 TCP_NODELAY

25
如果你在每次对套接字调用时设置TCP_QUICKACK选项,并先前设置了TCP_NODELAY选项,那么QUICKACK选项会覆盖NODELAY吗?
连接时:
int i = 1;
setsockopt( iSock, IPPROTO_TCP, TCP_NODELAY, (void *)&i, sizeof(i));

每次写入:

int i = 1;
setsockopt( iSock, IPPROTO_TCP, TCP_QUICKACK, (void *)&i, sizeof(i));

TCP_QUICKACK调用会使之前的TCP_NODELAY调用失效吗?


当您这样做并使用类似Wireshark的工具监视行为时,会发生什么? - Andy Finkenstadt
4
使用 getsockopt 函数,我已验证 TCP_QUICKACK 不会覆盖 TCP_NODELAY。 - donalmg
为什么每次写入时都要这样做?对于每个接收到的数据包,都会发送一个ACK,因此在每次recv之后应该设置TCP_QUICKACK,或者我漏掉了什么吗? - Aditya Sehgal
为什么需要同时使用quickack和nodelay?通常设置nodelay就可以解决问题。 - lxgr
2
@lxgr TCP_QUICKACK 影响接收器;TCP_NODELAY 影响发送器。如果您无法控制两个端点,则可能需要设置这两个设置以获得所需的网络性能。 - congusbongus
4个回答

36

这两个选项之间并没有直接的关系,它们只是用于不同的目的。

TCP_NODELAY 的目的是禁用/启用分段缓冲,以便尽快将数据发送给对等方,因此通常用于提高网络利用率。 TCP_QUICKACK 用于尽早发送确认消息而不是在某些协议级别的交换下延迟,并且它不稳定/永久,随后的TCP事务(可能发生在幕后)根据实际协议级别处理或任何实际设置和堆栈行为之间的任何实际分歧可能会忽略此选项。

注意TCP_NODELAY 是可移植的,而TCP_QUICKACK 不是(仅适用于 Linux 2.4 .4+)。


16
请使用TCP_QUICKACK,而不是TCP_NODELAY。
启用TCP_NODELAY具有类似的效果,但对于小写入可能会使吞吐量变差。如果您编写一个循环,仅使用“write()”将几个字节(最坏情况下为一个字节)发送到套接字,并且使用TCP_NODELAY禁用了Nagle算法,则每个写操作都成为一个IP数据包。这将使流量增加40倍,并为每个有效负载添加IP和TCP标头。 Tinygram防止在飞行中有第二个数据包时发送第二个数据包,除非您有足够的数据来填充最大大小的数据包。它积累一轮回时间的字节,然后将队列中的所有内容发送出去。这几乎总是你想要的。如果您设置了TCP_NODELAY,则需要更加注意缓冲和刷新问题。对于大多数HTTP传输,这些都无关紧要。 (我从未研究过这对SSL握手的影响,这可能很重要。)简短版本:设置TCP_QUICKACK。如果您发现这会使事情变得更糟,请告诉我。 John Nagle

https://news.ycombinator.com/item?id=10608356


6

简短回答

  • 要禁用 Nagle 缓冲算法,请使用 TCP_NODELAY 套接字选项。
  • 要禁用延迟 ACK,请使用 TCP_QUICKACK 套接字选项。

详细信息

  • Nagle算法

    • 以其创造者John Nagle的名字命名的Nagle算法是一种通过减少在网络上发送的小数据包数量来提高TCP效率的机制之一。
    • 目标是防止节点在应用程序向套接字传递数据较慢时传输许多小数据包。
    • 如果一个进程导致许多小数据包被传输,它可能会创建不必要的网络拥塞。特别是当数据包的有效负载小于TCP头数据时,这一点尤为明显。
  • 延迟确认

    • TCP延迟确认或延迟ACK是TCP的一种实现技术,旨在提高网络性能并减少拥塞。
    • 延迟ACK的发明是为了减少确认段所需的ACK数,并减少协议开销。
    • 延迟ACK意味着TCP不会立即确认每个接收到的TCP段。多个ACK响应可以合并成一个响应,从而减少协议开销。
  • Nagle算法和延迟ACK在TCP/IP网络中不兼容

    • 延迟ACK尝试在每个段中发送更多的数据。但是,Nagle算法的一部分依赖于ACK来发送数据。

    • Nagle算法和延迟ACK一起会产生问题,因为延迟ACK在等待发送ACK,而Nagle算法在等待接收ACK。

    • 示例

      客户端:嗨!这是第一个数据包
      服务器:<沉默,等待第二个数据包,好吧,我最终会确认>
      客户端:<沉默,好吧,我在等待ACK,也许有网络拥塞>
      服务器:好吧,我无聊了。这是一个ACK
      客户端:太好了,这是第二个数据包!
      服务器:太棒了,我们完成了
      
      • 客户端之所以这样做是因为Nagle算法,而服务器之所以这样做是因为延迟ACK。
  • 如何解决Nagle算法和延迟ACK引起的问题

    • 通过服务器上的全局套接字选项启用TCP_NODELAY以禁用Nagle算法
    • 在代理服务器和负载均衡器上进行配置调整:如果您运行的应用程序或环境只有时而具有高度交互式流量和喋喋不休的协议,则此项特别相关。通过在负载均衡器级别上动态切换Nagle算法和TCP_NODELAY的开关,您可以使即使是高度异构的流量混合也能以最佳状态运行。
    • 减少服务器和负载均衡器上的延迟ACK计时器。有时,这种优化是在软件中处理的,在应用程序级别,但当情况不是这样时,您仍然可以在服务器或负载均衡器级别上动态管理ACK计时器。
    • 在进行这些更改时,请仔细观察您的网络流量,并查看每个调整对拥塞的影响。

更多细节请参考this


5

TCP_QUICKACKTCP_NODELAY影响TCP中的不同操作。在tcp(7)手册页中,描述了哪些TCP套接字选项会相互干扰,例如TCP_CORKTCP_NODELAY


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