TCP 拥塞窗口原理

滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度。

拥塞窗口,也就是本文要讲的。

概念

一个连接的TCP双端只是网络最边缘的两台主机,他们不知道整个网络是如何工作的,因此他们不知道彼此之间的有效吞吐量。因此,他们必须找到一种方法来确定它。我们称之为拥塞窗口 (CWND)。这是在我们必须停止并等待确认之前可以发送的字节数。

拥塞窗口是决定任何时候可以发出的字节数的因素之一。拥塞窗口由发送方维护,是阻止发送方和接收方之间的链路因流量过多而过载的一种手段。这不应与发送方维护的滑动窗口相混淆,滑动窗口的存在是为了防止接收方过载。拥塞窗口是通过估计链路上有多少拥塞来计算的。

拥塞窗口对于设备来说是本地的,并且永远不会在连接上共享,这与在每个段中发送的接收器窗口不同。在任何给定时间,设备最多可以发送由接收器窗口和拥塞窗口之间的最小值指定的字节数,如下面的公式所示:

transmittable bytes = min(cwnd, rwnd)

这意味着如果拥塞窗口小于接收窗口,则设备可以在等待确认之前传输多达拥塞窗口中定义的字节数。相反,如果接收窗口小于拥塞窗口,则设备可以在等待确认之前最多传输接收器窗口中定义的字节数。

拥塞窗口根据网络拥塞动态变化。每次未确认段时,都假定是由于网络拥塞。拥塞窗口随时间演变的方式被定义为一个算法,这取决于实现。我们现在将介绍最常见的一种。该算法遵循以下规则:

拥塞窗口从一个段的大小开始(大约 1KB)

定义了一个拥塞窗口阈值(ssthresh)

如果收到确认,并且当前拥塞窗口大小小于 ssthresh,则拥塞窗口加倍

如果收到确认,但拥塞窗口大于或等于 sshthresh,则拥塞窗口增加其初始值(例如 1KB)

如果一个段没有被确认从而触发重传,拥塞窗口就会减半并且 ssthresh 被放置在这个值

拥塞窗口不能大于接收器窗口

该规则中包括我们经常听过的几种算法:

慢启动(slow-start)

拥塞避免(congestion avoidance)

快速重传(fast retransmit)

快速恢复(fast recovery)

算法

通过下面的图片,可以方便大家更加快速的理解拥塞窗口的算法机制。

TCP 拥塞窗口原理

从上图中可以看出,每个设备都会跟踪自己的拥塞窗口(CWND,绿色)和对端的接收器窗口 (RWND)。

慢启动

当主机开始发送数据时,如果立即所大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理。

每经过一个传输轮次,拥塞窗口 cwnd 就加倍。一个传输轮次所经历的时间其实就是往返时间RTT。不过“传输轮次”更加强调:把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。

另,慢开始的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,使得发送方在开始时只发送一个报文段(目的是试探一下网络的拥塞情况),然后再逐渐增大cwnd。

下面,我们从示例图着手,来分析慢启动的过程。

在协商连接时,两个设备交换它们的接收器窗口(在这种情况下它们都有 32KB)

双端都以 1KB 的拥塞窗口开始,但由于在该示例中客户端将是唯一发送数据的客户端,因此它将是唯一一个显着使用此值的客户端。

在第 2 行,客户端收到一个 ACK并将其 CWND 加倍(现在是 2k)

服务器在第 3 行收到一个ACK时也做同样的事情

客户端发送两段 1k 的数据,它们稍后在第 6 行和第 7 行确认,其中客户端上的拥塞窗口加倍(4k,然后是 8k)

然后,客户端再次发送 1k 数据并立即得到确认,有效地再次将拥塞窗口加倍(现在第 9 行为 16k)。

这在第 10-11 行重复,其中 CWND 达到 32k。

此时,除非接收端窗口也增长,否则拥塞窗口不能再增长。

慢启动的整个过程如下:

初始化 cwnd = 1

经过1个RTT,即收到一个ACK,cwnd = 2^(1) = 2

经过2个RTT, cwnd = 2^(2) = 4

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgpzy.html