拥塞处理可以认为是TCP最重要的网络功能,拥塞的实现算法对TCP整体效率(吞吐量、传输速率等)有很大的影响。TCP拥塞实现算法是针对各种复杂的网络环境,从这点上看,一个UDP的应用采用简化了的TCP拥塞算法,在相对简单的网络环境下能得到对TCP更好的传输效率。
拥塞发生判定条件
1. 数据段(segment)发送超时
数据段发送超时,说明这个数据段或该数据段的ACK在传输的过程中丢失了;网络状况不理想,产生拥塞了。
2. 收到重复的ACK
看下面的一个数据段丢失的情形:
Sender Receiver
| |
|-------- segment1-------> |
|<-------ACK1--------------- |
| |
|-----segment2-----X-----> |
| |
|---------segment3-------> |
|<---------ACK1------------- |
segment2在传输的过程中丢失了,TCP是基于流机制确认的,它还是返回ACK1,发送方就收到了一个重复的ACK。这里的一个重点是,当数据段乱序时,发送方也会收到重复的ACK。怎么判断是数据包丢失还是乱序?如果同时收到3或3个以上的重复ACK,就认为数据包丢失了,认为网络发生拥塞。
拥塞控制方法
当发送数据段产生超时时,说明网络已经产生拥塞,TCP会执行慢启动,快速地减少数据段的传送。如果收到3个或以上的重复ACK,认为某个数据段丢失了,这个时候,TCP一般会采用快速恢复的拥塞策略来控制发送数据流量:即马上重发丢失的数据段,然后采用快速恢复算法。某些TCP实现这个时候也会慢启动的算法来控制流量,这样很多时候会降低网络的传输的效率。因为,发送方有收到ACK,说数据在网络两端还是流动的,拥塞程度还不是很严重,应该用更高效的策略。
1. 慢启动
除了一个滑动窗口大小外,引入一个拥塞窗口大小,记为cwnd。前者是接收方可接受的最大数据的大小,后者是发送方允许的最大发送数据大小。对于发送方来说,最大可发送的数据的大小应该是两者之间的较小值。开始发送数据时,cwnd=1个数据段(大小事SYN中对方通告的MSS), 接下来每收到一个ACK,cwnd就以2^n方增长。慢启动,其实不慢。
2. 快速恢复
引入ssthresh, ssthresh = cwnd / 2, 重传丢失的数据段,cwnd重新设为,cwnd = ssthresh + 3 * MSS.
每收到一个重复ACK,cwnd增加一个分组大小,重传一个数据段。
收到新的ACK,设置cwnd为ssthresh,其实就是原来的cwnd减半。