TCP流量控制和拥塞控制机制
TCP流量控制和拥塞控制机制
cwnd:发送端窗口( congestion window ),拥塞窗口大小
rwnd:接收端窗口(receiver window),与接受方的TCP数据报缓冲区大小有关
实际发送窗口大小= Min [ rwnd, cwnd ]
当rwnd < cwnd 时,是接收方的接收能力限制发送方窗口的最大值。
当cwnd < rwnd 时,则是网络的拥塞限制发送方窗口的最大值。
MMS:maximum segment size,最大分节大小,为TCP数据包每次传输的最大数据分段大小
RTO:(Retransmission TimeOut)即重传超时时间。
- 流量控制是点对点通信量的控制,主要就是抑制发送端发送数据的速率,以便接收端来得及接收。
- 拥塞控制是防止过多的数据注入到网络中,针对整个网络。
1、流量控制
一次发送一个字节,并且需要确认应答,效率太低,发送所有数据又可能来不及接收。
TCP使用折中的方式:滑动窗口协议,发送方和接收方都有滑动窗口。
窗口大小就是发送端在没有接收到确认应答时可以发送的数据大小。
利用滑动窗口机制,通过接收端返回的rwnd控制发送方的流量
TCP的窗口单位是字节,不是报文段,发送方的发送窗口不能超过接收方给出的接收窗口的数值。
暂停发送
1、当接收方来不及接收数据时。接收方会发送一个通告窗口为0的ACK,这种情况下发送方必须暂停发送数据,直到一个新的带非零窗口的通告(ACK)收到为止。
2、为了避免非零窗口的通告丢失,发送方在收到零窗口后启用persistence timer,每个一段时间发送1个字节的探测数据包,直到窗口重新打开为止。
从上图,三条加粗的B的确认应答,可以看出接收方的主机 B 进行了三次流量控制:
- 把窗口减小到 rwnd = 300;
- 把窗口减小到 rwnd = 100;
- 最后减小到 rwnd = 0,即不允许发送方在发送数据了。
这种发送方暂停发送将持续到主机 B 重新发出一个新的窗口值为止。
2、拥塞控制
因特网建议标准RFC2581定义了进行拥塞控制的四种算法,即慢开始(Slow-start)、拥塞避免(Congestion Avoidance)、快重传(Fast Restrangsmit)和快回复(Fast Recovery)
慢开始和拥塞避免
拥塞窗口(也叫发送端窗口):
发送方维持一个拥塞窗口 cwnd ( congestion window )的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。
2.1、慢开始算法
- 初始化:cwnd=1mss;
- 以后每收到一个ack,cwnd+=1mss(结果就是每次发送cwnd变大两倍);
- 相当于指数增大
在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值(cwnd=1)。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理。
为了防止拥塞窗口cwnd增长过大引起网络拥塞,还需要设置一个慢开始门限ssthresh状态变量(如何设置ssthresh),初始慢开始门限为16。慢开始门限ssthresh的用法如下:
- 当 cwnd < ssthresh 时,使用上述的慢开始算法。
- 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
- 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。
2.2、拥塞避免算法
图5-25中①
- 当cwnd超过ssthresh(慢启动阈值)时,每收到一个ack,拥塞窗口:cwnd+=1/cwnd(结果就是每次发送,cwnd+1);
- 相当于加法增大,这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。
2.3、超时重传:
图5-25中②
情况:如果发送方设置的超时计时器时限已到但还没有收到确认,那么很可能是网络出现了拥塞,致使报文段在网络中的某处被丢弃
- cwnd越来越大,导致有包丢失,没有接收到确认。这时需要重传数据。
- ssthresh=max(cwnd/2, 2) 这个的意思是cwnd/2 但是至少是2个报文段
- cwnd=1,重新进入慢启动,cwnd变化:1,2,4,8,12,13,14;因为ssthresh为12,然后开始线性增大
2.4、快速重传:
图5-25中④
快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时才进行捎带确认。当发送方收到3次重复的ack,就立即重传数据。
- ssthresh=max(cwnd/2, 2);
- 把cwnd再设置为ssthresh的值(具体实现有些为ssthresh+3)
- 重新进入拥塞避免阶段。
与快速恢复一起使用
2.5、快速恢复(Reno)
图5-25中⑤
-
ssthresh=max(cwnd/2, 2);
-
cwnd=ssthresh+3MSS;
-
每收到重复的ack,cwnd+=1MSS;
-
当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值。原因是因为该ACK确认了新的数据,说明从重复ACK时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。
当收到新的ack时,cwnd重设为ssthresh,并退出快速恢复阶段。cwnd=ssthresh,然后进入加法增大(拥塞避免)
2.6 NewReno
可以看出Reno的快速重传算法是针对一个包的重传情况的,然而在实际中,一个重传超时可能导致许多的数据包的重传,因此当多个数据包从一个数据窗口中丢失时并且触发快速重传和快速恢复算法时,问题就产生了。因此NewReno出现了,它在Reno快速恢复的基础上稍加了修改,可以恢复一个窗口内多个包丢失的情况。具体来讲就是:Reno在收到一个新的数据的ACK时就退出了快速恢复状态了,而NewReno需要收到该窗口内所有数据包的确认后才会退出快速恢复状态,从而更一步提高吞吐量。
2.7 SACK
SACK就是改变TCP的确认机制,最初的TCP只确认当前已连续收到的数据,SACK则把乱序等信息会全部告诉对方,从而减少数据发送方重传的盲目性。比如说序号1,2,3,5,7的数据收到了,那么普通的ACK只会确认***4,而SACK会把当前的5,7已经收到的信息在SACK选项里面告知对端,从而提高性能,当使用SACK的时候,NewReno算法可以不使用,因为SACK本身携带的信息就可以使得发送方有足够的信息来知道需要重传哪些包,而不需要重传哪些包。