谈谈TCP控制那些事( 二 )


不过这时候可能会遇到一个问题,假如接收方发送的通知报文,由于某种网络原因,这个报文丢失了,这时候就会引发一个问题:接收方发了通知报文后,继续等待发送方发送数据,而发送方则在等待接收方的通知报文,此时双方会陷入一种僵局 。
为了解决这种问题,我们采用了另外一种策略:当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段时间就发个测试报文去询问接收方,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器 。
拥塞控制的算法我们在开始假定:

  1. 数据是单方向传递,另一个窗口只发送确认;
  2. 接收方的缓存足够大,因此发送方的大小的大小由网络的拥塞程度来决定 。
慢开始算法:cwnd的大小取决于网络的拥塞程度,并且动态地在变化 。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口 。
慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小 。
这里用报文段的个数作为拥塞窗口的大小举例说明慢开始算法,实际的拥塞窗口大小是以字节为单位的 。
一个传输轮次所经历的时间其实就是往返时间RTT,而且没经过一个传输轮次(transmission round),拥塞窗口cwnd就加倍 。
为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量 。ssthresh的用法如下:当cwnd<ssthresh时,使用慢开始算法 。当cwnd>ssthresh时,改用拥塞避免算法 。当cwnd=ssthresh时,慢开始与拥塞避免算法任意
注意,这里的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,然后逐渐增大,这当然比按照大的cwnd一下子把许多报文段突然注入到网络中要“慢得多” 。
拥塞避免算法拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍 。这样拥塞窗口按线性规律缓慢增长 。
无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半(但不能小于2) 。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法 。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕 。
  1. 拥塞窗口cwnd初始化为1个报文段,慢开始门限初始值为16
  2. 执行慢开始算法,指数规律增长到第4轮,即cwnd=16=ssthresh,改为执行拥塞避免算法,拥塞窗口按线性规律增长
  3. 假定cwnd=24时,网络出现超时(拥塞),则更新后的ssthresh=12,cwnd重新设置为1,并执行慢开始算法 。当cwnd=12=ssthresh时,改为执行拥塞避免算法
乘法减小(Multiplicative Decrease)和加法增大(Additive Increase)
“乘法减小”指的是无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半,并执行慢开始算法,所以当网络频繁出现拥塞时,ssthresh下降的很快,以大大减少注入到网络中的分组数 。“加法增大”是指执行拥塞避免算法后,使拥塞窗口缓慢增大,以防止过早出现拥塞 。常合起来成为AIMD算法 。
注意:“拥塞避免”并非完全能够避免了阻塞,而是使网络比较不容易出现拥塞 。
TCP两个重要窗口滑动窗口滑动窗口是接受数据端使用的窗口大小,用来告知发送端接收端的缓存大小,以此可以控制发送端发送数据的大小,从而达到流量控制的目的,对应==>rwnd:接收端窗口(receiver window)
对于流量控制,是一个端对端的概念 。由接收端返回的rwnd控制 。
拥塞窗口那么对于数据的发送数据端就是拥塞窗口,拥塞窗口不代表缓存,拥塞窗口指某一源端数据流在一个RTT内可以最多发送的 数据包 数,cwnd:发送端窗口( congestion window ) 。
发送端数据结构为了保证顺序性,每?个包都有?个ID 。在建?连接的时候,会商定起始的ID是什么,然后 按照ID?个个发送 。为了保证不丢包,对于发送的包都要进?应答,但是这个应答也不是?个?个来的,?是会应答某个之前 的ID,表示都收到了,这种模式称为累计确认或者累计应答(cumulative acknowledgment) 。为了记录所有发送的包和接收的包,TCP也需要发送端和接收端分别都有缓存来保存这些记录 。发送端的缓存?是按照包的ID ?个个排列,根据处理的情况分成四个部分 。第?部分:发送了并且已经确认的 。这部分就是你交代下属的,并且也做完了的,应该划掉的 。第?部分:发送了并且尚未确认的 。这部分是你交代下属的,但是还没做完的,需要等待做完的回复之后,才能划掉 。第三部分:没有发送,但是已经等待发送的 。这部分是你还没有交代给下属,但是?上就要交代的 。第四部分:没有发送,并且暂时还不会发送的 。这部分是你还没有交代给下属,?且暂时还不会交代给下属的 。在TCP?,接收端会给发送端报?个窗?的??,叫Advertised window 。这个窗 ?的??应该等于上?的第?部分加上第三部分,就是已经交代了没做完的加上?上要交代的 。超过这个窗?的,接收端做不 过来,就不能发送了 。于是,发送端需要保持下?的数据结构 。


推荐阅读