原文:TCP流量控制与拥塞控制 | Andrew's Blog
追求高速的传输速率是当今网络的永恒主题,但有时候我们也需要对发送方进行控制以提供流量控制服务和拥塞控制服务。这一片文章就介绍一下TCP的流量控制服务和拥塞控制服务。
流量控制
流量控制的定义
前面讲过,一条TCP连接每一侧主机都为该连接设置了接收缓存。当该TCP连接收到了正确的、按序的字节后,他就将数据放入接收缓存。相关联的应用进程会从该缓存中读取数据。但不必是数据一到达就立即读取。事实上,接收方也许正忙于其他任务,甚至要过很长时间后才读取该数据。如果某个应用进程读取比较缓慢,但是发送方发送的太多、太快,发送的数据就会很容易地使该连接的接收缓存溢出。
TCP为它的应用程序提供了流量控制服务(flow-control service)以消除发送方使接收方缓存溢出的可能性。流量控制因此是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。
流量控制的实现
TCP通过让发送方维护一个称为接收窗口(receive window)的变量(TCP报文段首部的接收窗口字段)来提供流量控制。通俗的讲,接收窗口用于给发送方一个指示--该接收方还有多少可用的缓存空间。因为TCP是全双工通信,在连接两端的发送方都各自维护了一个接收窗口。
如上图所示RcvBuffer
是接收缓存的总大小,buffered data
是当前已经缓存了的数据,而free buffer space
是当前剩余的缓存空间大小,rwnd
的值就是free buffer space
。主机B通过把当前的rwnd
值放入到它发送给主机A的报文段首部的接收窗口字段中,通知主机A它在该连接的缓存中还有多少可用空间。
而主机A则将自己发往主机B的序号空间中未确认的数据量控制在rwnd
值的范围内,这样就可以避免主机A使主机B的接收缓存溢出。
拥塞控制
为什么需要拥塞控制?
我们在前面讲到过,在TCP协议中,分组丢失一般是当网络变得拥塞时由路由器缓存溢出引起的。因此分组重传是作为网络拥塞的征兆来对待,但是却无法处理导致网络拥塞的原因,因为有太多的源想以过高的速率发送数据。一旦网络发生拥塞,分组所经历的时延会变大,分组丢失的可能性会变大,发送端需要重传的分组会变多,这只会导致网络越来越拥塞,形成恶性循环。因此,为了处理网络拥塞,需要一些机制以在面临网络拥塞时遏制发送方。
拥塞控制方法
在实践中采用了两种主要的拥塞控制方法,这两种方法是根据网络层是否为传输层拥塞控制提供了显示帮助来区分。它们是端到端拥塞控制和网路辅助的拥塞控制。
- 端到端拥塞控制
在端到端的拥塞控制中,网路层没有为运输层提供显示支持。即使网络中存在拥塞,端系统也必须通过对网络行为的观察(如分组的丢失与时延)来推理判断之。 - 网络辅助的拥塞控制
在网络辅助的拥塞控制中,网络层构件(即路由器)向发送方提供关于网络中拥塞状态的显示反馈信息。拥塞信息从网络反馈到发送发通常有两种方式:直接反馈信息可以由网络路由器发给发送方,这种方式的通知通常采用一种阻塞分组的形式;第二种方法是路由器标记或更新从发送方流向接收方的分组中的某个字段来指示拥塞的产生,一旦收到一个标记的分组后,接收方就会向发送方发送该网络拥塞指示。
TCP拥塞控制
TCP是通过端到端的方法来解决拥塞控制的,因为IP层不会向端系统提供有关网络拥塞的反馈信息。TCP报文段的丢失被认为是网络拥塞的一个迹象,TCP会相应的减小其窗口长度。这里我们需要明确的几个问题是:
1.TCP发送方如何限制它向其连接发送流量的速率?
2.TCP发送方如何感知从它到目的地之间的路径上存在拥塞呢?
3.当感知到了拥塞时,采用何种算法来改变其发送速率呢?
首先我们来考虑TCP发送方怎样限制它向网络发送流量的速率。与流量控制一样,在发送方的TCP拥塞控制机制中跟踪了一个额外的变量,即拥塞窗口(congestion window)。拥塞窗口表示为cwnd,通过这个拥塞窗口,我们就能够对发送方向其连接发送数据的速率进行限制。具体的措施是:让一个发送方中未确认的数据量不会超过cwnd和rwnd的最小值,即:
1 | LastByteSend - LastByteAcked <= min{cwnd,rwnd} |
LastByteSend,LastByteAcked分别是最后一个发送的字节的序号和最后一个被确认的字节的序号。
如前所述TCP发送方通过捕获到丢包时间的产生感知从它到目的地之间的路径上存在拥塞。
在拥塞情况发生时,我们可以通过减小cwnd的值来减小发送方发送数据的速率。那么如果没有拥塞发生呢?如果没有拥塞,我们应该增加cwnd的值来增大发送方发送数据的速率。发送方发送速率过大会导致网络拥塞,甚至拥塞崩溃;而如果发送方过于谨慎,发送太慢则不能充分利用带宽。因此根据网络情况合理设置cwnd的值非常重要。
在概述了TCP拥塞控制之后,现在我们来考虑一下广受赞誉的TCP拥塞控制算法。该算法包括三部分:慢启动,拥塞避免,快速恢复。
慢启动
当一条TCP连接开始,cwnd值通常初始置为一个MSS较小值。这使得初始发送速率为MSS/RTT。在慢启动(slow-start)状态,cwnd的值以1个MSS开始并且每当传输的报文段首次被确认就增加一个MSS。
何时结束慢启动阶段的指数增长呢?
①如果存在一个由超时指示的丢包事件,TCP发送方将cwnd设置为1并重新开始慢启动过程。它还将第二个状态变量的值ssthresh(慢启动阈值)设置为cwnd/2,即当检测到拥塞时将ssthresh置为拥塞窗口值的一半。
②当检测到拥塞时ssthresh设为cwnd的一半,当到达或超过ssthresh的值时,结束慢启动并且TCP转移到拥塞避免模式。
③如果检测到3个冗余ACK,这时TCP执行一种快速重传并进入快速恢复状态。
拥塞避免
每个RTT只将cwnd的值增加一个MSS:对于TCP发送方无论何时到达一个新的确认,就将cwnd增加一个MSS(MSS/cwnd)字节。例如,如果MSS是1460字节,并且cwnd是14 600字节,则在一个RTT内发送10个报文段。每个到达ACK增加1/10MSS的拥塞窗口长度,因此在收到对所有10个报文段的确认后,拥塞窗口的值将增加了一个MSS。当出现超时时,TCP的拥塞避免与慢启动阶段一样。当出现丢包时,网络继续从发送方向接收方交付报文段,当接收到3个冗余ACK时,将ssthresh的值置为cwnd的一半,同时将cwnd的值减半加上3个MSS。
快速恢复
1)对收到的每个用冗余ACK,cwnd值增加一个MSS。
2)当对丢失报文段的一个ACK到达时,TCP在降低cwnd进入拥塞避免状态。
3)如果出现超时事件,执行如同慢启动和拥塞避免中相同的动作后,迁移到慢启动状态.