本文引用图片均来自 高军: 计算机网络
流量控制
流量控制就是控制发送方的数据发送速率
,避免接收方接收出错。TCP的流量控制由滑动窗口
机制实现
在下例中假设主机A、B
已经建立了TCP连接并且协商好滑动窗口大小为400
,主机A每次发送的报文携带100字节
的数据,为方便描述
将待发送数据按照100字节一个小格
划分好
由于窗口大小为400,那么主机A可以在收到主机B的确认之前将前4个格子的数据都发送出去。假设主机A发送了前3个格子(1-300)
的数据,其中前2次
报文顺利被接收,第3次
报文丢失
主机B收到1-200的数据后返回确认报文
,报文首部中确认字段ack
值201
是对主机A发送的1-200字节数据的确认
,窗口大小字段rwnd
值300
表明主机B的接收窗口
大小现在是300
主机A收到确认报文后调整
窗口大小为300并向前移动窗口,此时1-200的数据被移出
窗口,300-500的数据被移入
窗口。此时主机A可以将300-500的数据发送出去,而200-300的数据则会触发超时重传
如此循环往复
最终完成数据传送
上述简单的几个步骤其实就是整个流量控制过程的缩影,双方建立连接时协商
一个窗口大小。在后续数据传输过程中,接收方根据自己的接收能力
使用报文首部的窗口大小字段
控制窗口的变化,发送方根据接收方的确认报文
不断调整发送窗口大小。发送方根据累计确认
将已被确认接收的旧数据移出
窗口,将新数据移入
窗口。在窗口中的数据都发送完毕后不能再发送新数据,但是可以重传
旧数据
来考虑一个特殊情况,假设某次接收数据后接收方缓存区
满了,此时接收方会将窗口大小调整为0
,发送方收到报文后也将窗口大小调整为0
且不再发送数据
等后面接收方能接收数据了便向发送方发送报文,其中窗口大小调整为300。但是,这个通告报文丢失了
,那么接收方将一直处于发送窗口为0无法发送数据的状态,接收方则一直处于等待数据的状态,双方因为相互等待而形成死锁
为了避免上述问题,TCP为每个连接设定了一个持续计时器
,只要任何一方收到了对方的零窗口通知
计时器就启动。当计时器超时,发送方会发送仅携带1字节数据
的零窗口探测报文
给对方,接收方收到报文则返回自己的窗口大小
。如果接收窗口仍然为0
,那么发送方将重启
计时器,如果窗口大小不为0那么死锁局面就被打破
如果零窗口探测报文丢失则会触发超时重传
TCP规定即使接收窗口为0接收方也必须接收零窗口探测报文段、确认报文段以及携带紧急数据的报文段
,这也是零窗口探测报文能起作用的原因
拥塞控制
在某段时间,若对网络中的某一资源的需求超过
了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫做拥塞
,若不对拥塞进行控制网络的吞吐量
会随着输入负荷
的增大而下降
在理想拥塞控制情况下,网络吞吐量达到饱和之前
其吞吐量应该等于输入负载,吞吐量随输入负载增加而增加。在吞吐量饱和之后
输入负载继续增加会导致分组丢失
的情况,但网络能保持最大载荷
运行
如果没有拥塞控制,网络吞吐量的上升会随着输入负载的增加而越来越慢
,也就是说此时已经有部分分组因为输入负载的增加而丢失
,此时网络的吞吐量明显小于
理想吞吐量,处于轻度拥塞
状态。当输入负载增大到某一数值,网络的吞吐量开始减小,此时处于拥塞状态
。最终当输入负载到达某一临界值
,网络吞吐量减小为0
,此时网络进入死锁状态
无法工作
综上可以知道,对网络进行拥塞控制是很有必要的,实际的拥塞控制曲线应该尽可能接近
理想控制曲线
TCP主要有4种拥塞控制算法:
- 慢开始
- 拥塞避免
- 快重传
- 快恢复
下面举例简单介绍这4种算法,为简单起见我们假定数据是单向传送
的且发送方窗口大小仅由
网络拥塞程度决定
发送方维护维护以下变量:
拥塞窗口 cwnd
:如果网络没有拥塞就增大,否则减小发送窗口 swnd
:大小等于cwnd慢开始门限 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)
,此时发送方重新进入慢开始状态
慢开始是指一开始向网络注入的报文
少,不是cwnd增长慢。拥塞避免并不是说
能够避免拥塞,而是控制cwnd的增长
使得网络不容易出现拥塞
在拥塞控制算法中,如果报文因为某些原因
丢失(如途径路由器故障)导致发送方超时重传
,算法会误认为网络出现拥塞而将cwnd重新设置为1回到慢开始状态,这会降低
传输效率。为了解决这种因为个别报文丢失导致的状态回退
问题,快重传算法应运而生
快重传是指发送方尽快进行重传
而不是等到超时才重传,其要点如下:
- 要求接收方
不要
等待自己发送数据时才进行捎带确认,而是立即
发送确认 - 即使收到了
失序
的报文段也要立即发出对已收到报文的重复确认
- 发送方一旦收到
3个连续的重复确认
,就将相应的报文段立即重传
,而不是等待计时器超时再重传
如下例,发送方发送了M1、M2、M3
报文段,其中M3
丢失,发送方只收到对M1、M2
的确认报文。接着发送方发送M4、M5、M6
报文段,接收方收到M4后发现是乱序报文
,于是返回M2的重复确认
,M5和M6同理。在发送方收到3次M2的重复确认
后就知道M3丢失,于是不等
计时器超时便重传M3
据统计,使用快重传可以使网络吞吐量提高约20%
发送方收到三次重复确认也就知道了丢失的只是个别报文而不是网络拥塞,此时启动快恢复算法
而不是慢开始算法。快恢复算法会将cwnd和ssthresh
调整为当前cwnd的一半
,然后执行拥塞控制算法
参考文献
- 【1】高军: 计算机网络