计算机网络之TCP拥塞控制
1.详细讲一下拥塞控制
TCP 一共使用了四种算法来实现拥塞控制:
*慢开始 (slow-start);
*拥塞避免 (congestion avoidance);
*快速重传 (fast retransmit);
*快速恢复 (fast recovery)。
发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。当cwndssthresh时,改用拥塞避免算法。
*慢开始:不要一开始就发送大量的数据,由小到大逐渐增加拥塞窗口的大小。
*拥塞避免:拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1而不是加倍。这样拥塞窗口按线性规律缓慢增长。
*快重传:我们可以剔除一些不必要的拥塞报文,提高网络吞吐量。比如接收方在**收到一个失序的报文段后就立即发出重复确认,而不要等到自己发送数据时捎带确认。
重传规定:发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
*快恢复:
主要是配合快重传。当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半(为了预防网络发生拥塞),但接下来并不执行慢开始算法,因为如果网络出现拥塞的话就不会收到好几个重复的确认,收到三个重复确认说明网络状况还可以。
2.TCP的拥塞控制
拥塞控制
思路讲解: TCP 拥塞机制也是个高频考点,需要掌握它跟流量控制的区别,也需要掌握拥塞控制的这几种算法:慢启动算法、拥塞避免、快速重传、快速恢复算法。
拥塞控制是作用于网络的,防止过多的数据包注入到网络中,避免出现网络负载过大的情况。它的目标主要是最大化利用网络上瓶颈链路的带宽。它跟流量控制又有什么区别呢?流量控制是作用于接收者的,根据接收端的实际接收能力控制发送速度,防止分组丢失的。
我们可以把网络链路比喻成一根水管,如果我们想最大化利用网络来传输数据,那就是尽快让水管达到最佳充满状态。
发送方维护一个拥塞窗口 cwnd(congestion window) 的变量,用来估算在一段时间内这条链路(水管)可以承载和运输的数据(水)的数量。它大小代表着网络的拥塞程度,并且是动态变化的,但是为了达到最大的传输效率,我们该如何知道这条水管的运送效率是多少呢?
一个比较简单的方法就是不断增加传输的水量,直到水管快要爆裂为止(对应到网络上就是发生丢包),用 TCP 的描述就是:
★ 只要网络中没有出现拥塞,拥塞窗口的值就可以再增大一些,以便把更多的数据包发送出去,但只要网络出现拥塞,拥塞窗口的值就应该减小一些,以减少注入到网络中的数据包数。
实际上,拥塞控制主要有这几种常用算法
● 慢启动
● 拥塞避免
● 拥塞发生
● 快速恢复
慢启动算法(慢开始)
cwnd初始值为1,每个轮次cwnd加倍
慢启动算法,表面意思就是,别急慢慢来。它表示 TCP 建立连接完成后,一开始不要发送大量的数据,而是先探测一下网络的拥塞程度。由小到大逐渐增加拥塞窗口的大小,如果没有出现丢包,每收到一个 ACK,就将拥塞窗口 cwnd 大小就加 1(单位是 MSS)。每轮次发送窗口增加一倍,呈指数增长,如果出现丢包,拥塞窗口就减半,进入拥塞避免阶段。
● TCP 连接完成,初始化 cwnd = 1,表明可以传一个 MSS 单位大小的数据。
● 每当收到一个 ACK,cwnd 就加一;
● 每当过了一个 RTT,cwnd 就增加一倍; 呈指数让升
为了防止 cwnd 增长过大引起网络拥塞,还需设置一个慢启动阀值 ssthresh(slow start threshold)状态变量。当cwnd到达该阀值后,就好像水管被关小了水龙头一样,减少拥塞状态。即当cwnd >ssthresh时,进入了拥塞避免算法。
拥塞避免算法
慢开始门限ssthresh,当cwnd>ssthresh时,进入拥塞避免,让cwnd每个轮次+1。出现超时,就令ssthresh = cwnd/2,重新进行慢开始。
一般来说,慢启动阀值 ssthresh 是 65535 字节,cwnd到达慢启动阀值后
● 每收到一个 ACK 时,cwnd = cwnd + 1/cwnd
● 当每过一个 RTT 时,cwnd = cwnd + 1
显然这是一个线性上升的算法,避免过快导致网络拥塞问题。
拥塞发生(快速重传)
接收方只对最后一个收到的有序报文段进行确认,若发送方介绍重复确认,就判断下一个报文段丢失,执行快重传,即立即重传下一报文段。
当网络拥塞发生丢包时,会有两种情况:
● RTO 超时重传
● 快速重传
如果是发生了RTO 超时重传,就会使用拥塞发生算法
● 慢启动阀值 sshthresh = cwnd /2
● cwnd 重置为 1
● 进入新的慢启动过程
这真的是辛辛苦苦几十年,一朝回到解放前。其实还有更好的处理方式,就是快速重传。发送方收到 3 个连续重复的 ACK 时,就会快速地重传,不必等待RTO 超时再重传。
慢启动阀值 ssthresh 和 cwnd 变化如下:
● 拥塞窗口大小 cwnd = cwnd/2
● 慢启动阀值 ssthresh = cwnd
● 进入快速恢复算法
快速恢复
若丢失个别报文段,执行快恢复,令ssthresh = cwnd/2, cwnd = ssthresh,直接进入拥塞避免。
快速重传和快速恢复算法一般同时使用。快速恢复算法认为,还有 3 个重复 ACK 收到,说明网络也没那么糟糕,所以没有必要像 RTO 超时那么强烈。
正如前面所说,进入快速恢复之前,cwnd 和 sshthresh 已被更新:
cwnd = cwnd /2 - sshthresh = cwnd
然后,真正的快速算法如下:
● cwnd = sshthresh + 3
● 重传重复的那几个 ACK(即丢失的那几个数据包)
● 如果再收到重复的 ACK,那么 cwnd = cwnd +1
● 如果收到新数据的 ACK 后, cwnd = sshthresh。因为收到新数据的 ACK,表明恢复过程已经结束,可以再次进入了拥塞避免的算法了。
总结
总结:
拥塞控制是为了防止过多数据注入网络,导致网络过载。TCP的拥塞控制采用四个算法实现:慢开始、拥塞避免、快重传、快恢复。 发送方维护一个拥塞窗口(cwnd)的状态变量。
● 慢开始:cwnd初始值为1,每个轮次cwnd加倍
● 拥塞避免:慢开始门限ssthresh,当cwnd>ssthresh时,进入拥塞避免,让cwnd每个轮次+1。出现超时,就令ssthresh = cwnd/2,重新进行慢开始。
● 快重传:接收方只对最后一个收到的有序报文段进行确认,若发送方介绍重复确认,就判断下一个报文段丢失,执行快重传,即立即重传下一报文段。
● 快恢复:若丢失个别报文段,执行快恢复,令ssthresh = cwnd/2, cwnd = ssthresh,直接进入拥塞避免。