TCP拥塞控制算法Reno

计算机网络

Posted by bbkgl on July 22, 2020

盈盈一水间

脉脉不得语

春招实习的时候,经过几次面试,发现这里都讲的不是很好,打算用心好好整一下。

为什么会有拥塞控制

如果说把网络链路比喻成一根水管,于是传输数据就成了给水管注水。

所以对应网络上能存在的数据量:

网络上能容量的数据包的数量(水管容量) = 链路带宽(水管截面积) x 往返延迟(水管长度)

img

这样存在的问题就是水的流量太大的时候,会发生爆管(本来设计水的流量是10立方米/分钟,因为管子太小,变成了1立方米/分钟),会导致所有水到达目的地的速度明显变慢,每单位体积的水在水管里停留的时间越长。

对应在网络中就是一个数据包收到回复确认的时间变长,于是数据包在网络链路里存在的时间也就越长,导致网络延迟高,丢包率变高。这个时候发送方会进行超时重传,于是网络状况就会越来越差。

为了解决这个问题,就出现了拥塞控制,控制水管的输入,也就是整体控制每个发送方的发送的速度,减少丢包率,相当于控制每个人发送的窗口大小。

TCP拥塞控制算法

主要讲Linux内核默认的Reno,然后顺带提一下Google的BBR。

Reno算法

Reno出现在几乎所有的计算机网络教材中,估计很多同学也已经忘了(包括我)。。。

其对拥塞的控制主要分为4个阶段:

  • 慢启动
  • 拥塞避免
  • 快重传
  • 快恢复

这里盗个图给帮助说明一下。

img

同样有对应的几个概念值:

  • 拥塞窗口(cwnd),这个其实和流量控制的窗口类似,都用来表示一次能发出去的数据量。这个值随时间变化,变化速度在慢启动和拥塞避免阶段不一样。其变化范围,由是否发生丢包来决定,发生丢包,值就会变成原来的一半。
  • 慢启动阈值(ssthresh),这是一个随丢包情况变化的值,用来作为慢启动和拥塞避免两个阶段的分界线。其第一次赋值是第一次发生丢包时,拥塞窗口(cwnd)值的一半。

慢启动阶段

慢启动意思就是拥塞窗口(cwnd)从最小值1开始变大。

img

而是将发送窗口的大小在初始的情况下设置为1,在收到接收方确认后,再修改其发送窗口为原来的两倍,也就是2。这样子的话,就是指数增长。

叫慢启动的原因估计就是发因为发送窗口是从1开始增长的,与后面的快恢复形成对比。

一般在慢启动阶段,碰到第一次丢包的时候会将慢启动阈值(ssthresh)设为当前窗口大小值的一半。

而慢启动到拥塞避免的分界线就是慢启动阈值(ssthresh)。

慢启动阶段

在慢启动阶段达到阈值(ssthresh)后就会进入拥塞避免阶段,拥塞避免阶段窗口的增长是线性的,。

img

这个阶段会持续到发生下一次丢包(超时)。如果发生了超时(TO),就会将阈值(ssthresh)设置为当前窗口的一半,然后窗口大小从1重新开始慢启动算法(慢恢复)。

快重传

快重传一定发生在乱序接收的情况下,A给B一次发送了[3, 4, 5, 6]个包,假设此时5发生了丢包,这个时候B确认回复了3和4,也就是A收到了 [ACK(4), ACK(5), ACK(5)]。A会继续发送[7, 8, 9, 10],此时A收到的确认就是 [ACK(5), ACK(5), ACK(5), ACK(5)],收到了3次或以上的重复确认,此时A就会直到5号数据包丢包,不等5号的计时器超时,便直接重传5号数据包,这就是TCP快速重传。

快恢复

快恢复算法是和快重传配合使用的算法,一般发生了快重传的时候,发送方能收到三次连续重复确认,说明此时网络并不是拥塞,只是单纯的丢包。此时会将阈值(ssthresh)设置为当前窗口的一半,然后窗口大小从阈值(ssthresh)重新开始拥塞避免算法(快恢复)。

这里与前面发生丢包后的慢恢复形成对比。其实也是Reno算法和Tahoe算法的一个区别,Tahoe算法是没有快恢复的。

BBR算法

太复杂了,再说吧。