Nagle算法、TCP确认延迟机制、TCP_CORK

版权声明:guojawee https://blog.csdn.net/weixin_36750623/article/details/84945186

两种类型的TCP报文段简介

成块数据、交互数据
1、在TCP传输数据流中,存在两种类型的TCP报文段,一种包含成块数据(通常是满长度的,携带一个报文段最多容纳的字节数),另一种则包含交互数据(通常只有携带几个字节数据)。

2、举例说明什么样的数据是“交互数据”? ==> 从键盘输入的一个字符,占用一个字节,可能在传输上造成41字节的包,其中包括1字节的有用信息和40字节的首部数据。这种情况转变成了4000%的消耗,这样的情况对于轻负载的网络来说还是可以接受的,但是重负载的福特网络就受不了了,它没有必要在经过节点和网关的时候重发,导致包丢失和妨碍传输速度。吞吐量可能会妨碍甚至在一定程度上会导致连接失败。

3、对于成块数据的报文段,TCP采用正常的流程发送即可,因为数据利用率很高。而对于交互数据的报文段,数据利用率就显得很低,在网络环境不好的情况下容易加重网络负担。所以TCP必须对交互数据单独处理。

Nagle算法

Nagle算法是一种拥塞控制算法,为了防止网络中充斥着大量的“交互数据”。

1、数据的一次成功的发送,要经过“发送、接收到ACK”。为了尽可能的利用网络带宽,TCP总是希望一次性尽可能的发送足够大的数据(一个连接会设置MSS参数,因此,TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据)。

2、Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

3、Nagle算法的核心思想是最多只能有一个未被确认的小段(所谓“小段”,指的是小于MSS尺寸的数据块)存在于网络,而待发送的其它小分组会被重新分组成一个”较大的”小分组,等收到上一个小分组的应答或长度达到MSS后再发送。

4、Nagle算法的规则(可参考tcp_output.c文件里tcp_nagle_check函数注释):
(1)如果数据包 长度达到MSS,则允许发送;
(2)如果数据包 含有FIN,则允许发送;
(3)设置了TCP_NODELAY选项,则允许发送;
(4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;
(5)上述条件都满足,但发生了超时(一般为200ms),则立即发送。

5、实际举例说明Nagle算法减少网络中微小分组的数量
比如客户端需要依次向服务器发送大小为1,2,3,1,2字节的5个分组:
在没有开启Nagle算法的情况下,这些小分组会被依次发送(不需要等待上一个小分组的应答),总共发送的报文段(分组)个数为5
当开启Nagle算法时,客户端首先发送大小为1字节的第一个分组,随后其它分组到达发送缓冲区,由于第一个分组的应答还没有收到,所以TCP会先缓存新来的这4个小分组,并将其重新分组,组成一个大小为8(2+3+1+2)字节的”较大的”小分组。当第一个小分组的应答收到后,客户端将这个8字节的分组发送。总共发送的报文段(分组)个数为2
⇒ ⇒ ⇒ 可以看到,当传输数据存在大量交互数据时,nagle算法可以有效减少网络中的报文段个数

禁止Nagle

什么情况下需要禁用Nagle算法? 默认情况下,发送数据采用Nagle 算法。这样虽然提高了网络吞吐量,但是实时性却降低了,一些交互性很强的应用程序 / 实时性强的应用程序需要使用TCP_NODELAY选项可以禁止Nagle 算法。

TCP_NODELAY:尽量不要等待,只要发送缓冲区中有数据,并且发送窗口是打开的,就尽量把数据发送到网络上去。

TCP_NODELAY适用场景:涉及到交互的服务器,比如ftp的接收命令的服务器,必须使用TCP_NODELAY。默认是TCP_CORK。设想一下,用户每次敲几个字节的命令,而下层在攒这些数据,想等到数据量多了再发送,这样用户会等到发疯。这个糟糕的场景有个专门的词汇来形容-----粘(nian拼音二声)包

#include <netinet/tcp.h>
...
void cancel_nagle(int fd)
{
    int val = 1;
    ::setsockopt(fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
}

TCP确认延迟机制

A向B发送了数据,B将不会立即回复ACK给A,而会在下面两种情况下才会回复ACK给A:
① B收到A发来的1个包,启动200ms定时器,还没超时,正好B要给对方A发点内容。于是对这个包的确认ack就跟着捎过去。这叫做“捎带发送”;
② B收到A发来的1个包,启动200ms定时器,等到200ms的定时器到点了(第二个包没来),于是对这个包的确认ack被发送。这叫做“延迟发送”;

要想使应用程序的实时性强,需要禁止Nagle算法、关闭TCP确认延时机制。

TCP_CORK 选项

所谓的CORK就是塞子的意思,形象地理解就是用CORK将连接塞住,使得数据先不发出去,等到拔去塞子后再发出去。设置该选项后,内核会尽力把小数据包拼接成一个大的数据包(一个MTU)再发送出去,当然若一定时间后(一般为200ms,该值尚待确认),内核仍然没有组合成一个MTU时也必须发送现有的数据(不可能让数据一直等待)。

TCP_CORK:尽量向发送缓冲区中攒数据,攒到多了再发送,这样网络的有效负载会升高。

TCP_CORK适用场景:webserver,下载服务器(ftp的发送文件服务器),需要带宽量比较大的服务器

Nagle算法与CORK算法区别
(1)Nagle算法主要避免网络因为太多的小包(协议头的比例非常之大)而拥塞,而CORK算法则是为了提高网络的利用率,使得总体上协议头占用的比例尽可能的小。
(2)Nagle算法关心的是网络拥塞问题,只要所有的ACK回来则发包(不关乎数据包大小),而CORK算法,如果发送的是几个小的数据包,则需要将数据包组合成一定大小,才可以发送出去。

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/84945186