计算机网络 (14) 运输层-TCP流量控制、拥塞控制

192 阅读8分钟

本文引用图片均来自 高军: 计算机网络

流量控制

流量控制就是控制发送方的数据发送速率,避免接收方接收出错。TCP的流量控制由滑动窗口机制实现

在下例中假设主机A、B已经建立了TCP连接并且协商好滑动窗口大小为400,主机A每次发送的报文携带100字节的数据,为方便描述将待发送数据按照100字节一个小格划分好

image.png image.png

由于窗口大小为400,那么主机A可以在收到主机B的确认之前将前4个格子的数据都发送出去。假设主机A发送了前3个格子(1-300)的数据,其中前2次报文顺利被接收,第3次报文丢失

主机B收到1-200的数据后返回确认报文,报文首部中确认字段ack201是对主机A发送的1-200字节数据的确认窗口大小字段rwnd300表明主机B的接收窗口大小现在是300

image.png image.png

主机A收到确认报文后调整窗口大小为300并向前移动窗口,此时1-200的数据被移出窗口,300-500的数据被移入窗口。此时主机A可以将300-500的数据发送出去,而200-300的数据则会触发超时重传

image.png image.png

如此循环往复最终完成数据传送

上述简单的几个步骤其实就是整个流量控制过程的缩影,双方建立连接时协商一个窗口大小。在后续数据传输过程中,接收方根据自己的接收能力使用报文首部的窗口大小字段控制窗口的变化,发送方根据接收方的确认报文不断调整发送窗口大小。发送方根据累计确认将已被确认接收的旧数据移出窗口,将新数据移入窗口。在窗口中的数据都发送完毕后不能再发送新数据,但是可以重传旧数据

来考虑一个特殊情况,假设某次接收数据后接收方缓存区满了,此时接收方会将窗口大小调整为0,发送方收到报文后也将窗口大小调整为0且不再发送数据

等后面接收方能接收数据了便向发送方发送报文,其中窗口大小调整为300。但是,这个通告报文丢失了,那么接收方将一直处于发送窗口为0无法发送数据的状态,接收方则一直处于等待数据的状态,双方因为相互等待而形成死锁

image.png

为了避免上述问题,TCP为每个连接设定了一个持续计时器,只要任何一方收到了对方的零窗口通知计时器就启动。当计时器超时,发送方会发送仅携带1字节数据零窗口探测报文给对方,接收方收到报文则返回自己的窗口大小。如果接收窗口仍然为0,那么发送方将重启计时器,如果窗口大小不为0那么死锁局面就被打破

如果零窗口探测报文丢失则会触发超时重传

image.png

TCP规定即使接收窗口为0接收方也必须接收零窗口探测报文段、确认报文段以及携带紧急数据的报文段,这也是零窗口探测报文能起作用的原因

拥塞控制

在某段时间,若对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫做拥塞,若不对拥塞进行控制网络的吞吐量会随着输入负荷的增大而下降

在理想拥塞控制情况下,网络吞吐量达到饱和之前其吞吐量应该等于输入负载,吞吐量随输入负载增加而增加。在吞吐量饱和之后输入负载继续增加会导致分组丢失的情况,但网络能保持最大载荷运行

如果没有拥塞控制,网络吞吐量的上升会随着输入负载的增加而越来越慢,也就是说此时已经有部分分组因为输入负载的增加而丢失,此时网络的吞吐量明显小于理想吞吐量,处于轻度拥塞状态。当输入负载增大到某一数值,网络的吞吐量开始减小,此时处于拥塞状态。最终当输入负载到达某一临界值,网络吞吐量减小为0,此时网络进入死锁状态无法工作

综上可以知道,对网络进行拥塞控制是很有必要的,实际的拥塞控制曲线应该尽可能接近理想控制曲线

image.png

TCP主要有4种拥塞控制算法:

  1. 慢开始
  2. 拥塞避免
  3. 快重传
  4. 快恢复

下面举例简单介绍这4种算法,为简单起见我们假定数据是单向传送的且发送方窗口大小仅由网络拥塞程度决定

发送方维护维护以下变量:

  1. 拥塞窗口 cwnd:如果网络没有拥塞就增大,否则减小
  2. 发送窗口 swnd:大小等于cwnd
  3. 慢开始门限 ssthresh:当cwnd < ssthresh使用慢开始算法,当cwnd > ssthresh使用拥塞避免算法

发送方判断网络拥塞的依据是有没有按时收到接收方的确认报文

发送方首先采用慢开始算法,从cwnd=1开始传输数据,此时传输1个窗口单位的数据。当收到接收方的确认后发送方认为网络没有拥塞便增大cwnd(乘法增长,此处假设为乘以2),此时cwnd=2,发送方可以传输2个窗口单位的数据。依次类推,如果后续的传输都没有出问题cwnd最终会等于ssthresh(ssthresh初始值设定为16)

当cwnd等于ssthresh后发送方将采用拥塞避免算法,此时cwnd的增大会放缓(加法增长,此处假设为加1),在网络不出现拥塞的情况下cwnd会保持缓慢增长。假设在cwnd=24时出现了丢包,发送方会因为收不到接收方的确认而触发超时重传,此时发送方判断网络出现拥塞。出现拥塞后发送方直接将cwnd调低到1,将ssthresh重新设定为出现拥塞时cwnd的一半(12),此时发送方重新进入慢开始状态

image.png

慢开始是指一开始向网络注入的报文少,不是cwnd增长慢。拥塞避免并不是说能够避免拥塞,而是控制cwnd的增长使得网络不容易出现拥塞

在拥塞控制算法中,如果报文因为某些原因丢失(如途径路由器故障)导致发送方超时重传,算法会误认为网络出现拥塞而将cwnd重新设置为1回到慢开始状态,这会降低传输效率。为了解决这种因为个别报文丢失导致的状态回退问题,快重传算法应运而生

快重传是指发送方尽快进行重传而不是等到超时才重传,其要点如下:

  1. 要求接收方不要等待自己发送数据时才进行捎带确认,而是立即发送确认
  2. 即使收到了失序的报文段也要立即发出对已收到报文的重复确认
  3. 发送方一旦收到3个连续的重复确认,就将相应的报文段立即重传,而不是等待计时器超时再重传

如下例,发送方发送了M1、M2、M3报文段,其中M3丢失,发送方只收到对M1、M2的确认报文。接着发送方发送M4、M5、M6报文段,接收方收到M4后发现是乱序报文,于是返回M2的重复确认,M5和M6同理。在发送方收到3次M2的重复确认后就知道M3丢失,于是不等计时器超时便重传M3

image.png

据统计,使用快重传可以使网络吞吐量提高约20%

发送方收到三次重复确认也就知道了丢失的只是个别报文而不是网络拥塞,此时启动快恢复算法而不是慢开始算法。快恢复算法会将cwnd和ssthresh调整为当前cwnd的一半,然后执行拥塞控制算法

image.png

参考文献