TCP采用基于窗口的方法进行拥塞控制。该方法属于闭环控制方法。 TCP发送方维持一个拥塞窗口CWND (Congestion Window)
拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送端利用拥塞窗口根据网络的拥塞情况调整发送的数据量。
所以,发送窗口大小不仅取决于接收方公告的接收窗口, 还取决于网络的拥塞状况,所以真正的发送窗口值为:
控制拥塞窗口的原则
只要网络没有出现拥塞,拥塞窗口就可以再增大一 些,以便把更多的分组发送出去,这样就可以提高网络的利用率。但只要网络出现拥塞或有可能出现拥塞,就必须把拥塞窗口减小一些,以减少注入到网络中的分组数, 以便缓解网络出现的拥塞。
拥塞的判断
重传定时器超时:现在通信线路的传输质量一般都很好,因传输出差错而丢弃分组的概率是很小的(远小于1 %)。只要出现了超时,就可以猜想网络可能出现了拥塞。
收到三个相同(重复)的ACK :个别报文段会在网络中丢失,预示可能会出现拥塞(实际未发生拥塞),因此可以尽快采取控制措施,避免拥塞。
TCP拥塞控制算法
四种(RFC 5681):
- 慢开始(slow-start)
- 拥塞避免(congestion avoidance)
- 快重传(fast retransmit)
-
快恢复(fast recovery)
1、慢开始(Slow start)
用来确定网络的负载能力。算法的思路:由小到大逐渐增大拥塞窗口数值。
初始拥塞窗口cwnd设置: 旧的规定:在刚刚开始发送报文段时,先把初始拥塞窗口cwnd设置为1至2个发送方的最大报文段SMSS (Sender Maximum Segment Size) 的数值。 新的RFC 5681 把初始拥塞窗口cwnd设置为不超过2至4 个SMSS 的数值。 慢开始门限ssthresh(状态变量):防止拥塞窗口 cwnd增长过大引起网络拥塞。
拥塞窗口cwnd控制方法:在每收到一个对新的报文段的确认后,可以把拥塞窗口增加最多一个SMSS 的数值。
其中N是原先未被确认的、但现在被刚收到的确认报文段所确认的字节数。 不难看出,当N<SMSS 时,拥塞窗口每次的增加量要小于SMSS。 用这样的方法逐步增大发送方的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。
发送方每收到一个对新报文段的确认(重传的不算在内)就使cwnd加1(报文段的个数为单位)。
使用慢开始算法后,每经过一个传输轮次 (transmission round),拥塞窗口cwnd就加倍。 一个传输轮次所经历的时间其实就是往返时间RTT。
“传输轮次”更加强调:把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。 例如,拥塞窗口cwnd = 4,这时的往返时间RTT就是发送方连续发送4个报文段,并收到这4个报文段的确认,总共经历的时间。
设置慢开始门限状态变量ssthresh
慢开始门限ssthresh的用法如下:当cwnd<ssthresh时,使用慢开始算法。当cwnd>ssthresh时,停止使用慢开始算法而改用拥塞避免算法。 当cwnd=ssthresh时,既可使用慢开始算法,也可使用拥塞避免算法。
2、拥塞避免算法
思路:让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1, 而不是加倍,使拥塞窗口cwnd按线性规律缓慢增长。
因此在拥塞避免阶段就有“加法增大” (Additive Increase) 的特点。这表明在拥塞避免阶段,拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。
无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(重传定时器超时):
- ssthresh = max(cwnd/2,2)
- cwnd=1
- 执行慢开始算法
这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
当TCP连接进行初始化时,将拥塞窗口置为1。图中的窗口单位不使用字节而使用报文段。 慢开始门限的初始值设置为16 个报文段,即ssthresh =16。
发送端的发送窗口不能超过拥塞窗口cwnd和接收端窗口rwnd中的最小值。我们假定接收端窗口足够大, 因此现在发送窗口的数值等于拥塞窗口的数值。
在执行慢开始算法时,拥塞窗口cwnd=1,发送第一个报文段。
发送方每收到一个对新报文段的确认ACK,就把拥塞窗口值加1,然后开始下一轮的传输(请注意,横坐标是传输轮次,不是时间)。因此拥塞窗口cwnd随着传输轮次按指数规律增长。
当拥塞窗口cwnd增长到慢开始门限值ssthresh时 (图中的点1,此时拥塞窗口cwnd =16),就改为执行拥塞避免算法,拥塞窗口按线性规律增长。
“拥塞避免”并非指完全能够避免了拥塞。利用以 上的措施要完全避免网络拥塞还是不可能的。
“拥塞避免”是说在拥塞避免阶段把拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。
当拥塞窗口cwnd=24 时,网络出现了超时(图中的点2),发送方判断为网络拥塞。于是调整门限值 ssthresh = cwnd / 2 = 12,同时设置拥塞窗口 cwnd = 1,进入慢开始阶段。
按照慢开始算法,发送方每收到一个对新报文段的确认ACK,就把拥塞窗口值加1。 当拥塞窗口cwnd = ssthresh = 12时(图中的点3, 这是新的ssthresh值),改为执行拥塞避免算法,拥塞窗口按线性规律增大。
当拥塞窗口cwnd = 16时(图中的点4),出现了一个新的情况,就是发送方一连收到3个对同一个报文段的重复确认(图中记为3-ACK)。发送方改为执行快重传和快恢复算法。
3、快重传算法
采用快重传FR (Fast Retransmission) 算法可以让发送方尽早知道发生了个别报文段的丢失。
快重传算法首先要求接收方不要等待自己发送数据时才进行捎带确认,而是要立即发送确认,即使收到了失序的报文段也要立即发出对已收到的报文段的重复确认。
发送方只要一连收到三个重复确认,就知道接收方确实没有收到报文段,因而应当立即进行重传(即 “快重传”),这样就不会出现超时,发送方也不就会误认为出现了网络拥塞。 使用快重传可以使整个网络的吞吐量提高约20%。
不难看出,快重传并非取消重传计时器,而是在某些情况下可更早地重传丢失的报文段。
4、快恢复算法
当发送端收到连续三个重复的确认时,由于发送方现在认为网络很可能没有发生拥塞, 因此现在不执行慢开始算法,而是执行
快恢复算法FR (Fast Recovery)
:
(1) 慢开始门限ssthresh =当前拥塞窗口cwnd/ 2 ;
(2) 新拥塞窗口cwnd=慢开始门限ssthresh;
(3) 开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大。
因此,在图的点4,发送方知道现在只是丢失了个别的报文段。于是不启动慢开始,而是
执行快恢复算法
。 这时,发送方调整门限值ssthresh = cwnd / 2 = 8, 同时设置拥塞窗口cwnd = ssthresh = 8(见图中的点 5),并开始执行拥塞避免算法。
可以看出,在拥塞避免阶段,拥塞窗口是按照线性规律增大的。这常称为“加法增大”AI (Additive Increase)。
当出现超时或3个重复的确认时,就要把门限值设置为当前拥塞窗口值的一半,并大大减小拥塞窗口的数值。这常称为“乘法减小”MD (Multiplicative Decrease)。
二者合在一起就是所谓的AIMD 算法。采用这样的拥塞控制方法使得TCP的性能有明显的改进。
发送方的发送窗口的上限值应当取为接收方窗口 rwnd 和拥塞窗口 cwnd 这两个变量中较小的一个, 即应按以下公式确定:
当 rwnd < cwnd 时,是接收方的接收能力限制发送窗口的最大值。
当 cwnd < rwnd 时,则是网络的拥塞限制发送窗口的最大值。
也就是说,rwnd和cwnd中数值较小的一个,控制了发送方发送数据的速率。