37-tcp协议——糊涂窗口综合征和nagle算法

1. 糊涂窗口综合征

  假设一种这么情况,当发送方的应用进程发送数据的速度比较慢,或者接收方的应用进程读取数据速度比较慢,又或者双方都有。但无论是对哪一种情况,都会让发送数据很小,这将会降低tcp的性能。

  比如,接收方的缓存空间已经满了,接收方进程每次从缓存中只读1字节数据,而缓存每次也只腾出1字节的空间,然后向发送方发送确认,设置窗口为1字节,这样会导致发送方每次也只发送1字节的数据(发送方的窗口大小是由接收方的窗口rwnd控制的),如果加上tcp首部和ip首部的话,总共有41字节的数据,但实际的数据只有1字节,这会导致当前网络流量的利用率非常低,tcp的性能也就降低了,如果再加上物理层和数据链路层的开销,tcp的性能就会更低,这种情况一般称为糊涂窗口综合征(中文翻译为糊涂窗口综合症,简称SWS)。


2. 由发送方引起的糊涂窗口综合征

  也就是说,这种情况是由可能发生在发送方或接收方任何一方的,要解决这种情况,我们需要在任何一方采取有效措施避免。那么可以让接收方等待一段时间,直到接收窗口能容纳一个最大报文段(mss)或者接收方缓存腾出一半空间。对于发送方来说,必须等待可以发送一个最大报文长度(mss) 或者发送接收方缓存空间至少一半长度的时候,才能发送数据。

  拿发送方来说,需要等待多长时间才合适?如果等待时间过长,则数据的处理过程则会延长,如果等待时间过短,还是有可能发送很小的数据报文,为此,可以使用nagle算法解决这种问题。


3. nagle算法

  nagle算法要求一个tcp连接上最多只有一个已经发送但是未被确认的小分组(即少量数据的分组),且在这个分组被确认之前不能发送其他的小分组。这样tcp就会在发送缓存中积累这些数据比较小的分组,再组装成一个较大的分组,直到收到接收方发来的确认,然后把这个较大的分组发送出去。也就是说,发送方每次都会积累了足够的分组装成最大报文长度(mss)发送出去

37-tcp协议——糊涂窗口综合征和nagle算法_第1张图片
图1-nagle算法

  如上图所示,假设开启了nagle算法,发送方给接收方发送了一个hello,但是由于现在接收方缓存只剩下一个字节大小的空间,于是发送方此时只发送了一个字母h,就会等待被确认。然后又分别发送了e,l,l,o数据,但是发送方会把e,l,l,o这几个数据组装成一个较大的报文(ello),等待接收方的缓存腾出足够的空间再一起发送出去。

  而nagle算法的巧妙之处在于,它权衡适应了发送方进程产生数据的速率和网络处理数据的速率。如果发送方进程产生数据的速率比网络处理数据的速率要快,那么组装成的最大报文长度就更大,否则就更小一些。

37-tcp协议——糊涂窗口综合征和nagle算法_第2张图片
图2-nagle算法应用场景

  如上图所示,一般来说,同处于同一局域网络下(192.168.0.0是局域网段)的两台主机R1和R2之间通信,时延一般是在10ms左右的(如果超过10ms,则说明当前局域网络的流量是有问题的),因为网络环境相对来说是比较稳定的,时延也比较短。因此在局域网下两台主机间通信很少使用nagle算法。


4. nagle算法实验

  一般tcp默认是开启nagle算法的,下面我们通过一个实验来验证下,这个实验的要求是:R1每次给R2发送一个字母x,总共发送5次,然后我们通过wireshark抓包工具把R1和R2之间交互的数据包抓取下来并分析,看是否使用了nagle算法。

37-tcp协议——糊涂窗口综合征和nagle算法_第3张图片
图3-nagle算法实验

  在图3中,216,217,218这三个数据包是R1和R2建立tcp连接的过程,236是R1发送的第一个数据包,从数据部分来看,236只发送了一个字节数据。然后237是对236的确认包,如果236没有被确认此时不能发送其他小分组(因为nagle算法规定:如果已经发送了一个小分组,在这个小分组被确认前,是不能发送其他小分组)。

37-tcp协议——糊涂窗口综合征和nagle算法_第4张图片
图4-nagle算法实验

  在这个过程中,可以收集其他4个小分组然后装成一个较大的分组再一起发送出去,通过下图可以发现,R1把4个小分组装成一个大的分组(即238报文)发送出去了。


5. 关闭nagle算法

37-tcp协议——糊涂窗口综合征和nagle算法_第5张图片
图5-关闭nagle算法

  当我们关闭nagle算法的时候,R1每发一个字节数据,就会封装成一个报文发送出去,在关闭nagle算法情况下,网络流量的利用率是非常低的,导致tcp的性能大大降低了。而启动nagle算法的情况下,在任一时刻也只能有一个包在传输,在这个包被确认前不能发送其他包,这样就减少了较小的包数目,提高了tcp通信的性能。

   有一点需要明白,无论是关闭还是开启nagle算法,并没有绝对的好坏,这只是相对的。比如在某些情况下nagle算法就不适合,比较典型的就是要求时延尽量小的应用,比如在网络游戏中,人物的动作需要及时的传输以确保不会影响玩家的的体验。


   一般nagle算法默认是开启的,如果不想使用的话可以在socket编程中可以使用TCP_NODELAY选项来关闭Nagle算法。



对应的实验具体参考自:
https://blog.csdn.net/q1007729991/article/details/70053346

你可能感兴趣的:(tcp/ip协议修炼心法)