在什么情况下应该/不应该使用它们?
首先,它们两个都不能禁用 Nagle 算法。
Nagle 算法是为了减少网络中的小数据包数量。该算法的原理是:如果数据大小小于一个限制(通常是 MSS),则等待接收之前发送的数据包的 ACK,并在此期间从用户处累积数据。然后发送累积的数据。
if [ data > MSS ]
send(data)
else
wait until ACK for previously sent data and accumulate data in send buffer (data)
And after receiving the ACK send(data)
这将有助于像telnet这样的应用程序。然而,等待ACK可能会增加发送流数据时的延迟。此外,如果接收器实现了“延迟ACK策略”,它将导致临时死锁情况。在这种情况下,禁用Nagle算法是更好的选择。
因此,TCP_NODELAY用于禁用Nagle算法。
TCP_CORK积极地累积数据。如果在套接字中启用了TCP_CORK,则在缓冲区填满到固定限制之前,它不会发送数据。与Nagle算法类似,它也从用户那里累积数据,但直到缓冲区填满到固定限制而不是收到ACK。这在发送多个数据块时非常有用。但是,在使用TCP_CORK时必须更加小心。
直到2.6内核,这两个选项是互斥的。但在后来的内核中,它们都可以同时存在。在这种情况下,TCP_CORK将被赋予更高的优先级。
参考:
TCP_NODELAY
用于禁用 Nagle 算法以优化 TCP/IP 网络并减少数据包数量,等到之前发送的数据得到确认后再发送累积的数据包。
//来源于 tcp(7) 手册:
TCP_CORK
(在 FreeBSD 中为 TCP_NOPUSH
)
若启用,则不会发送部分帧。所有已排队的部分帧都将在该选项被取消时一次性发送。这对于在调用 sendfile(2)
前添加头文件或进行吞吐量优化非常有用。按目前实现,TCP_CORK
可以最长使输出被缓存 200 毫秒。如果达到此上限,则排队的数据将自动传输。从 Linux 2.5.71 开始,此选项只能与 TCP_NODELAY
结合使用。不应在旨在可移植的代码中使用此选项。
这是一种优化,就像任何一种优化一样:
基本上,目的是避免发送多个帧,而可以使用单个帧通过sendfile()及其相关函数来发送。
例如,在Web服务器中,您可以先将标题和文件内容组装在内存中,然后文件可以直接由内核发送。TCP_CORK允许您将标题和文件的开头作为单个帧发送,即使使用了TCP_NODELAY,否则第一个块也会立即发送。
TCP_CORK是TCP_NODELAY的相反。前者强制数据包积累延迟,而后者则禁用它。
TCP_CORK
不是 TCP_NODELAY
的相反选项。Nagle算法在等待返回ACK时聚合数据,而后者禁用了它;前者则基于缓冲区压力聚合数据。 - joshperry