其他分享
首页 > 其他分享> > 传输层协议TCP—滑动窗口(6)

传输层协议TCP—滑动窗口(6)

作者:互联网

传输控制

      TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在前面的章节中,我们介绍了 TCP 连接的相关概念,也介绍了 TCP 为什么说是一种面向字节流的协议,也基本介绍了为什么说 TCP 是可靠的协议。但是 TCP 中的“C”——控制(Control),体现在哪里呢?在数据传输的过程中,TCP 又是如何控制的呢?要研究 TCP 中的控制,首先要看 TCP 的上下文,如下图5-82所示:

        

      就例如上图来说,TCP 的控制,就是面向发送者(进水速度)、接收者(出水速度)、发送方缓存(发送侧蓄水池)、接收方缓存(接收侧蓄水池)、网络(带宽、QoS(时延、丢包、抖动))的一个控制协议,它既要保证传输的可靠,也要面对各方面的复杂情况。

1.1 滑动窗口

1.1.1 滑动窗口基本概念

        TCP 引入滑动窗口的最直接的原因是“接收方的缓存是有限的”。在 “5.2.7 TCP 连接的收发空间”,我们介绍过,TCP 发送方的最大允许发送字节数,也就是发送方的发送窗口(SND.WND),是由其接收报文中的 Window 字段(SEG.WND)所决定的,即 SND.WND = SEG.WND。SND.WND 是 TCP 发送空间其中1个概念,如下图所示:

        

        SND.WND 称为滑动窗口。顾名思义,是可以滑动的。也就说滑动窗口是动态变化的,如图5-85所示:

        

       这个矩形在 X轴上的左坐标为 WL(window left)、右坐标为 WR(window right)。结合图5-84,我们知道:WL = SND.NXT、WR - WL = SND.WND。图5-85也指出了 WL 只能向右滑,WR 可以左右滑。实际上 WL 何时向右滑,滑多少,取决于 TCP 所发送的报文;WR 何时滑动(或左或右),滑多少,取决于 TCP 所接收的报文。如下图5-86所示:

        

       图5-86中,(1)T0时刻:WL = 7,WR = 12,WR - WL = SND.WND = 5。(2)在 T1 时刻,TCP 发送方,发送了1个报文,这个报文的数据长度是2个字节,于是我们看到了 WL 向右滑动:WL = 9。但是此时 WR 是不滑动的,因为 TCP 发送方还没有收到 TCP 接收方的指示。也正因为此,我们看到 T1 时刻,其滑动窗口的大小 SND.WND = 3,实际上是变小了。(3)在 T2 时刻,TCP发送方,接收了1个报文(对方的 ACK 报文),在这个报文中,其指示了接收窗口的大小等于6(SEG.WND = 6),于是我们看到:SND.WND = 6,同时也意味着 WR 向右滑动 WR = WL + SND.WND = 9 + 6 = 15。

      图5-86中,T2 时刻的 WR 是大于 T1 时刻的 WR,即 WR2 > WR1,但是在某些场景下也会出现 WR2 < WR1 的情形,如图5-87所示:

      

       上图5-87中,在 T2 时刻,TCP发送方,接收了1个报文(对方的 ACK 报文),在这个报文中,其指示了接收窗口的大小等于2(SEG.WND = 2),于是我们看到:SND.WND = 2,同时也意味着 WR 向右滑动 WR = WL + SND.WND = 9 + 2 = 11。而 WR1 = 12,WR2 = 11,即:WR2 < WR1。这种情形,TCP 称为窗口收缩(shrinking the window)。RFC 793 对待窗口收缩的态度是:强烈不建议,但是也不拒绝。

1.1.2 窗口大小与发送效率

       RFC 793 中所定义的 Window 字段有16个 bits,也就说滑动窗口最大可以为65535(不考虑 RFC 1323 的 TCP Window Scale Option)。那么,滑动窗口的大小,与传输效率有什么关系呢?可以用下面这一张图来说明:

       

       图5-88-上,表达的是一个比较大的滑动窗口(比如1000),此时它发送1个100字节长度的数据,只需1对报文(一来一回)即可,所花费的时间记为 t。图5-88-下,表达的是滑动窗口大小只为1的情形,此时它发送1个100字节长度的数据,则需要100对报文(一来一回)。我们忽略网络拥塞等因素,可以简单理解为它所花费的时间是100t。

       太小的滑动窗口(即使比1大一点),其引发的问题主要有:

      也正是鉴于此,TCP 其中有有很关键的一点就是致力于滑动窗口大小(size)的研究。

1.2 糊涂窗口综合症

       对于这种来来回回发送的小包,有一个专有称谓:糊涂窗口综合症(Silly Window Syndrome,SWS)。所谓小包,指的是 TCP 报文中的有效载荷(即数据部分)很小,甚至数据长度只有1个字节。这种情形所引发的问题还是比较大的。

       引发糊涂窗口综合症,有3种情形:或者是发送端、或者是接收端、或者是两者兼而有之。对于发送端来说,它产生数据的速度可能很慢(比如 telnet 程序),此时就会引发糊涂窗口综合症。对于接收端来说,原因也是如此——它处理数据的速度很慢——也会引发糊涂窗口综合症,如下图所述:

       

       如上图,接收方一次处理1个字节,仅仅是一个举例,事实上可以不是1个字节,只要是比较小的字节数即可,就会引发糊涂窗口综合症。如果不做一些特殊的处理,在 TCP 的世界里,糊涂窗口综合症几乎是必然要发生的,

1.2.1 接收方治疗方案

       接收方治疗方案基本可以归类为两种。

      当然,延迟确认的“延迟”时间不能过长,否则会让发送方以为发送超时,进而引发重新发送,这就弄巧成拙了。一般来说这个延迟时间是200 ms 或者500 ms(具体多少,是一个经验值),超过这个时间,接收方必须要给对方回应1个 ACK 报文。

1.2.2 发送方治疗方案

也有两种。第一种叫Nagle 算法,第二种是CORK 算法。

Nagle 算法

        Nagle 算法可以用一句话总结:大包随便发(大于等于 MSS),小包发1个要等到确才能发下1个。Nagle 算法的本质仍然是期望能“休息”或者等待一段时间,以使自己能将多个小包“攒”成1个大包发送。这个等待时间就是接收方 ACK 的时间。可以看到,如果对方 ACK 速度比较快,Nagle 算法仍然无法避免小包发送。

       需要说明的是,对于 FIN 报文,Nagle 算法是不等待的,立即发送,因为它并不想延迟 FIN 报文的发送。这句话的潜台词是:Nagle 算法对于其他报文是有可能造成延时的。另外,那些时延敏感的程序,如果遇到“发送方 Nagle 算法 + 接收方延迟确认”,那是雪上加霜:发送方在等接收方的确认,接收方又在等自己慢慢长大。所以,TCP 提供了一个选项“TCP_NODELAY”来禁用 Nagle 算法。

 

 

 

 

标签:窗口,WND,报文,TCP,发送,传输层,滑动,接收
来源: https://blog.csdn.net/weixin_45537413/article/details/113946807