白话讲解Nagle算法和延迟确认

以前对nagle算法有耳闻,利用TCP_NODELAY选项可以禁止他。然后看到延迟ack时,心想TCP_NODELAY选项与他有没有关系呢。其实没有,TCP_NODELAY只是用来禁用nagle算法的。关于他们之间的关系倒可以好好研究下。

有以下一个场景,村东和村西隔着一条大河,有几条船在两岸摆渡。由于每次要求过河的人只有一个,如果来一个人就将那个人摆渡过去(假设船只足够多),那势必运输效率非常低,而且大大浪费运输资源。可是过河人想尽快过河,而摆渡人又想多等几个人一起过河,于是尴尬的局面出现了,摆渡人与等船人经常在等船时间上发生争执。后来大家约定了发船的时间,前面那条船摆过去并返回之后,后面一条才发船,无论船上有多少人(没人肯定不算)。大家都觉得这个方案不错,在人数和等待发船的时间上达到了平衡,这才停止了矛盾的发生。

nagle算法实际上就是上面场景的体现。

在使用一些协议通讯的时候,比如Telnet,会有一个字节字节的发送的情景,每次发送一个字节的有用数据,就会产生41个字节长的分组,20个字节的IP Header 和 20个字节的TCP Header,这就导致了1个字节的有用信息要浪费掉40个字节的头部信息,这是一笔巨大的字节开销,而且这种Small packet在广域网上会增加拥塞的出现(例如在上面过河的场景中,河面上有过多的船只,肯定会造成拥塞)。这种现象还有个奇怪的名字,叫糊涂窗口综合症(Silly Windw Syndrome)。

Nagle算法是为了解决TCP数据发送端“糊涂窗口综合症”而产生的。他的思想也是,在没有收到已发送分组数据的回复ACK之前,不会发送其他分组。他要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组(对应过河的案例中,要求整个河面只有一条船)。相反,TCP收集这些少量的小分组,并在确认到来时以一个分组的方式发出去。

这里通过一个实验来看下Nagle算法对于发送的优化:
实验过程:Client端每次发送1个字节,将'hello'发送到Server端,然后server再全部发送给Client,其实要点在于Client的发送,预期的结果是:

1. 我们虽然一个字节一个字节的发,但是在协议中使用Nagle算法,可能会有延时等待的状况,即将几个字符合成一个片段进行发送.
2. 必须是收到对方的确认之后,才能再次发送.

结果是:
1. HELLO 被分成 2个包发送了,应用层调用send 5次,由于Nagle算法,将ELLO合成一个包发送,这样大可以减少Samll packet的数量,增加TCP传输的效率。
2. 分成的2个数据包,并没有连续被发出,这也符合Nagle算法的原则,即TCP连接上最多只能有一个未被确认的小分组,等待收到ACK之后,才发第二个封包。

默认情况下,发送数据采用Negale算法.这样虽然提高了网络吞吐量,但是实时性却降低了,在一些交互性很强的应用程序来说是不允许的,使用TCP_NODELAY选项可以禁止Negale 算法.
另外,CORK算法也可以达到和Nagle算法差不多的目的,这里就不多讲述。

其实还有个延迟确认问题,还是用上面过河的场景来说明。
过河是个双向的问题,河两岸都有人会过河。当摆渡人把客人送到对岸时,不会立马返回,而是会再等一段时间,以期待回头客,增加收入。或者摆渡人累了歇一会,期望和后面的摆渡人一起返回。

在TCP协议中,也有这样的延迟返回(即确认)的问题。一个叫累积确认,一个叫捎带确认。

  • 累积确认

有时候,发送方发送速度非常快,接收方一下下接收到了好几个 tcp 段,可以通过累积确认的方式,一次确认好几个 tcp 段,这样减少报文段的传输。

  • 捎带确认

有时候,双方互相发送数据,当接收到对方的 tcp 段后,先不着急确认,而是等待一会儿,连同数据和 ack 一起发送过去,这种情况叫捎带确认。如果等了一会儿(到时间了),接收方还没有数据要发送,那就直接回复一个纯 ack 过去,这样的 ack 称为延时的 ack(Delayed ACK)。

如果没有上述情况发生,ack延迟会等待多久发送呢?在linux上,所有的延时的 ack,延时时间都在 40 ms 左右(从收到数据到发送 ack 之间的时间)。

有没有禁止的延迟确认的方法,毕竟在实时性很高的场景,我们还是希望ack不要延迟的。有,tcp TCP_QUICKACK选项,不过好像这个选项的资料不是很多,貌似是一个附加选项。

我们看到TCP_NODELAY是针对Nagle算法的,而不是延迟确认,不要被字面意思误导。



参看:
https://www.cnblogs.com/purpleraintear/p/6051475.html
https://blog.csdn.net/u011130578/article/details/44873339
https://blog.csdn.net/ASKLW/article/details/79246694




















你可能感兴趣的:(linux网络编程,网络编程,白话经典算法)