TCP:Nagle算法和延迟确认

Nagle 算法(Nagle’s Algorithm)和延迟确认(Delayed ACK)是两种用于提高 TCP 协议性能的机制。它们旨在减少网络中的小数据包数量,从而提高网络效率。然而,这两种机制有时也会相互影响,导致性能问题。

Nagle算法

Nagle算法作用于发送端,其目的在于通过减少小数据包的发送,来减少网络的拥塞。
在讲解TCP三次握手的时候,我们提到TCP头部结构,其大小为20~60个字节。设想一下,如果我们要发送一个字节的数据,为了这一个字节,我们需要加上20字节的TCP头部,再加了20字节的IP头部,一共40字节的头部,就为了搭载这一个字节的数据,显得效率太低,于是就有了Nagle算法:

  • 发送数据时,如果当前有尚未确认的数据(已发出数据但还没收到ACK),则将数据缓存起来。
  • 所有未确认的数据都被确认后,TCP会发送缓冲区中的数据。
  • 如果缓冲区的数据大于MSS时,也会直接发送缓冲区的数据。

MSS(Maxinum Segment Size)指最大报文段长度,MSS的常见计算方式为 MTU(最大传输单元)减去20字节的TCP头部和20字节的IP头部,通常MSS值设置为1460字节。这个值有助于避免 IP 分片。


当启用Nagle算法的时候,我们发送多个小包,就会被合成一个大包,以及来减少网络中数据包的数量。但是,对于实时性要求较高的应用,这样做相当于带来延迟,并不适合。

我们可以通过设置TCP_NODELAY选项来关闭Nagle算法:

1
2
int enable = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));

延迟确认

Nagle算法是从发送端减少包的数据,而延迟确认则是从接收方的角度,通过减少ACK的数量,还达到减少网络拥塞的目的。

  • TCP收到数据包后,不立即发送ACK,而是等待一小段时间(通常是 200 毫秒)。
  • 在这个等待时间内,如果有数据需要发送,则将ACK和数据一起发送,这样可以减少单独的ACK包。
  • 在这个等待时间内,如果收到第二份数据,则发送ACK
  • 如果等待时间到期,还没有数据要发送,则发送ACK

TCP 连接中,客户端发送数据包,服务器收到后,如果立即发送 ACK,网络中会有大量的 ACK 包。启用延迟确认后,服务器在接收数据包后会等待一段时间,如果在这段时间内客户端继续发送数据,服务器可以一起确认多个数据包,减少 ACK 包数量。

Nagle算法和延迟确认导致的性能问题

Nagle在发送数据的环节增加了延迟,而延迟确认在接收的环节增加了延迟,如果发送方一直发小包,而接收方也没有数据返回的时候,可能会造成更多的延迟:

所以,在对延迟比较敏感的应用中,通常会关闭Nagle算法,来提高延迟。

参考资料


TCP:Nagle算法和延迟确认
https://blog.supersource.top/TCP_Nagle_and_Delayed_ACK/
作者
看热闹的咸鱼
发布于
2024年6月3日
许可协议