标题上这些概念很多,理解也有一定困难,尤其是它们之间的相互关系。这次就简单概括一下。
1.滑动窗口
接收端使用的流量控制。当接收端的应用程序从TCP缓存中提取数据速度过慢,导致TCP缓存中还有未被提取的数据,由于TCP缓存大小是固定的,则接收端下次能接收的数据量就变小了。
2.糊涂窗口综合症
当滑动窗口变为0的时候,则发送端不能再继续发送任何数据。若之后应用程序从TCP缓存中提取了几个字节的数据,则接收端会向发送端通告窗口更新了,你可以发数据过来了。但窗口只是更新了几个字节,而IP首部+TCP首部就有40字节,为了发这几个字节过来,会造成大量的带宽浪费。所以,可以在发送端和接收端采取一定措施,避免糊涂窗口综合征。
3.超时重传
当发送端发送数据,发生丢包时,则丢掉的包的ACK一直不会返回。此时发送端就一直等那个ACK返回,若超时,则重传该数据包。对于超时时间RTO,有很多复杂的算法。RTO的选择很重要,选短了,可能只是返回时间长但并未丢包,却当做丢包。选长了,迟迟不发丢的包也是个问题。
4.快速重传
如3所示,丢包了的处理方法不仅只有超时重传,还有快速重传。机制是:丢包了,接收端重复发送丢包前的ACK,发送端每发送一个包过来,接收端就发相同的ACK回去,这个ACK是对丢包之前的确认。当接收端连续收到3个相同的ACK,它就知道发生丢包了,根据ACK序号就能重发丢的包。
5.慢启动
慢启动的意思是,刚刚加入网络的连接,一点一点地提速,不要一上来就像那些特权车一样霸道地把路占满。
慢启动的算法如下(cwnd全称Congestion Window):
1)连接建好的开始先初始化cwnd = 1,表明可以传一个MSS大小的数据。
2)每当收到一个ACK,cwnd++; 呈线性上升
3)每当过了一个RTT,cwnd = cwnd*2; 呈指数让升
4)还有一个ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”(后面会说这个算法)
6.拥塞避免当cwnd >= ssthresh时,就会进入“拥塞避免算法”。一般来说ssthresh的值是65535,单位是字节,当cwnd达到这个值时后,算法如下:
1)收到一个ACK时,cwnd = cwnd + 1/cwnd
2)当每过一个RTT时,cwnd = cwnd + 1
这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。很明显,是一个线性上升的算法。
7.拥塞发生当丢包了,就意味着网络发生拥挤了,路由器缓存不够缓存包便丢弃。因此,丢包意味着拥塞发生。前面讲过丢包后,有两种不同的处理方法。而针对这两种不同的处理方法,会有不同的拥塞发生时的控制方法。
1)等到RTO超时,重传数据包。TCP认为这种情况太糟糕,反应也很强烈。
- sshthresh = cwnd /2
- cwnd 重置为 1
- 进入慢启动过程
2)快速恢复算法,也就是在收到3个重复 ACK时就开启重传,而不用等到RTO超时。
- TCP Reno的实现是:
- ssthresh = cwnd /2
- 进入快速恢复算法——Fast Recovery
- TCP Reno的实现是:
8.快速恢复算法
- cwnd = ssthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
- 重传Duplicated ACKs指定的数据包
- 因为重传丢掉的包到收到它的确认直接有个时间段,而这个时间段内接收端还是会发送重复的ACK,如果再收到 重复Acks,那么cwnd = cwnd +1
- 如果收到了新的Ack,那么,cwnd = ssthresh ,然后就进入了拥塞避免的算法了。
所以:
先慢启动,达到cwnd=ssthresh时,进入拥塞避免。
如果发生丢包,进入拥塞发生。因为丢包有两种不同处理办法,所以拥塞发生也有两种不同的处理办法。
1.计算ssthresh,cwnd,重新进入慢启动,再等到cwnd=ssthresh时,再次进入拥塞避免。
2.计算ssthresh,cwnd,快速重传,再等到cwnd=ssthresh时,再次进入拥塞避免。(步骤2就称为快速恢复)