文章目录
前言
阅读本文前请注意最后编辑时间,文章内容可能与目前最新的技术发展情况相去甚远。欢迎各位评论与私信,指出错误或是进行交流等。
本文是关于《计算机网络:自顶向下方法(第七版)》的学习分享,内容书写顺序也是按照书中的顺序。本文并不会提及书中的所有内容,主要写重点的知识,以及自己感兴趣的内容。会对原文中的内容进行一定的精简,或者加上个人的理解。
运输层
拥塞控制原理
在介绍TCP拥塞控制之前,我们先后退一步.在更广泛环境中讨论拥塞控制问题。在前面,我们已经分析了面临分组丢失时用于提供可靠数据传输服务的基本原理及特定的TCP机制。在实践中,这种丢包一般是当网络变得拥塞时由于路由器缓存溢出引起的。碰到丢包和网络拥塞,一般采用分组重传来对待,但是却无法处理导致网络拥塞的原因,因为有太多的源想以过高的速率发送数据。 为了处理网络拥塞,需要一些机制以在面临网络拥塞时遏制发送方。
拥塞原因与代价
我们通过分析3 个复杂性越来越高的发生拥塞的情况,开始对拥塞控制的一般性研究。 在每种情况下,我们首先关注出现拥塞的原因以及拥塞的代价(根据资源未被充分利用以及端系统得到的低劣服务性能来评价)。我们暂不关注如何对拥塞做出反应或避免拥塞,而是重点理解一个问题,即随着主机增加其发送速率并使网络变得拥塞,这时会发生的情况。
- 情况 1 : 两个发送方和一台具有无穷大缓存的路由器
两台发送主机 (A和 B) 都连接一台交换机,且这两条连接都和 源与目的地之间的单跳路由相连,两台接收主机C和D同理。

我们假设主机A 中的应用程序以 λin字节/秒的平均速率将数据发送到连接中,通过一个套接字将数据传递给运输层协议。该运输层协议是一个简单的协议。 数据被封装并发送;不执行差错恢复 (如重传)、流量控制或拥塞控制。 忽略由于添加运输层和更低层首部信息产生的额外开销,主机B 也以同样的方式运行,它也是以速率λin字节/秒发送数据。来自主机 A和主机B 的分组通过一台路由器,在一段传输速率为 R 的共享式输出链路上传输。该路由器带有缓存,可用于当分组到达速率超过该输出链路的容量时缓存分组。接收主机C和D接收的分组也在一段传输速率为 R 的共享式链路上接收数据,且它们都以速率λout字节/秒接收数据。在此第一种情况下,我们将假设路由器有无限大的缓存空间。

上图中左边的图形描绘了每个连接的吞吐量(接收方每秒接收的字节数)与该连接发送速率之间的函数关系。当发送速率在0~R/2之间时,接收方的吞吐量等于发送方的发送速率,即发送方发送的所有数据经有限时延后到达接收方。 然而当发送速率超过R/2 时,它的吞吐量只能达R/2。 这个吞吐量上限是由两条连接之间共享链路容量造成的。 链路不能以超过R/2 的稳定状态速率向接收方交付分组。 无论主机 A 和主机B将其发送速率设置为多高,它们都不会超过R/2 的吞吐量。取得每连接R/2 的吞吐量实际上看起来可能是件好事,因为在将分组交付到目的地的过程中链路被充分利用了。但是右边 的图形却显示了以接近链路容量的速率运行时产生的后果。 当发送速率接近R/2 时, 平均时延就会越来越大。 假设发送速率能超过R/2,路由器中的平均排队分组数就会无限增长,源与目的地之间的平均时延也会变成无穷大。虽然从吞吐量角度看,运行在总吞吐量接近R的状态也许是一个理想状态,但从时延角度看,却远不是一个理想状态。在这种(极端)理想化的情况中,我们已经发现了拥塞网络的一种代价,即当分组的到达速率接近链路容量时,分组经历巨大的排队时延。
此处平均时延会随着发送速率上升的原因,举个例子来解释。假设主机A和B发送速率低,每次都发送很少的数据,假设每秒共计发送10个字节。那么平均时延就是总时延除于总个数,第一个字节等待时延为0,假设第二个字节等待时延为a,那么第三个字节等待时延为2a,因为每个字节都要等前一个传输完毕后再轮到他,因此会逐步累加。因此总时延为 0 + a + 2a + ... 9a,除于总个数10。假设此时发送速率增大,变为每秒共计发送100个字节,那么平均时延也就会随着发送速率上升了。
- 情况2: 两个发送方和一台具有有限缓存的路由器
现在我们从下列两个方面对情况1 稍微做一些修改。首先,假定路由器缓存的容量是有限的。因此,当分组到达一个缓存已满的路由器时会
被丢弃。其次,我们假定每条连接都是可靠的,也就是能进行可靠数据传输。所以,如果一个运输层报文段的分组在路由器中被丢弃,那么它将被发送方重传。由于分组可以被重传,我们再次以λin字节/秒表示应用程序将初始数据发送到套接字中的速率。初始数据指的是第一次发送的数据,重传的分组不算初始数据。 运输层向网络中发送报文段 (包含初始数据或重传数据) 的速率用 λ'in 字节/秒表示。如图所示

首先考虑一种不真实的情况,即主机A能够以某种方式(不可思议地)确定路由器中的缓存是否空闲,因而仅当缓存空闲时才发送一个分组。 在这种情况下,将不会产生丢包, λin 与 λ'in 相等,并且连接的吞吐量就等于λin。从吞吐量的角度看,性能是理想的,即发送的
每个分组都被接收到。 注意到在这种情况下,平均主机发送速率不能超过R/2。
接下来考虑一种更为真实的情况,发送方仅当在确定了一个分组已经丢失时才重传。在这种情况下,如果主机A和B的发送速率总和超出了路由器传输速率,那么分组就会在路由器中进行排队,直至堆满。最后由于缓存溢出,后续到的分组会被丢弃,主机A和B就需要重传该分组。因此,传输的分组除了初始数据外,还有需要重传的分组。我们在此看到了另一种网络拥塞的代价,即发送方必须执行重传以补偿因为缓存溢出而丢弃(丢失)的分组。
最后,我们考虑下面一种情况:发送方也许会提前发生超时并重传在队列中巳被推迟但还未丢失的分组。在这种情况下,初始数据分组和重传分组都可能到达接收方。 当然,接收方只需要一份这样的分组副本就行了,重传分组将被丢弃。 在这种情况下,路由器转发重传的初始分组副本是在做无用功,因为接收方已收到了该分组的初始版本。 而路由器本可以利用链路的传输能力去发送另一个分组。 这里,我们又看到了网络拥塞的另一种代价,即发送方在遇到大时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本。
- 情况3: 4 个发送方和具有有限缓存的多台路由器及多跳路径
在最后一种拥塞情况中,有4 台主机发送分组,每台都通过交叠的两跳路径传输,如图所示。 我们再次假设每台主机都采用超时/重传机制来实现可靠数据传输服务,所有的主机都有相同的λin值,所有路由器的链路容量都是R字节/秒。

我们考虑从主机A到主机C的连接,该连接经过路由器R1 和R2。主机D到主机B的连接,该连接经过路由器R4 和R1。主机B到主机D的连接,该连接经过路由器R2 和 R1。对极小的λin值,路由器缓存的溢出是很少见的,吞吐量大致接近数据传输速度。 对稍大的λin值.对应的吞吐量也更大,因为有更多的初始数据被发送到网络中并交付到目的地,溢出仍然很少。 因此,对于较小的λin,λin的增大会导致λout的增大。当λin很大时,在路由器R2 上会接收 A-C和B-D的流量。因此,A-C流量与B-D流量在路由器R2上必须为有限缓存空间而竞争,所以当来自 B-D连接的数据传输速率越来越大时, A-C成功通过R2的流量会越来越小。
在上面提到的大流量的情况中,每当有一个分组在第二跳路由器上被丢弃时,第一跳路由器所做的将分组转发到第二跳路由器的工作就是"劳而无功"的。也许,第一跳路由器将分组转发到第二跳路由器的传输容量用来传送不同的分组可能更有效。所以,我们在此又看到了由于拥塞而丢弃分组的另一种代价,即当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了。
拥塞控制方法
在最为宽泛的级别上,我们可根据网络层是否为运输层拥塞控制提供了显式帮助,来区分拥塞控制方法。
- 端到端拥塞控制。在端到端拥塞控制方法中,网络层没有为运输层拥塞控制提供显式支持。 即使网络中存在拥塞,端系统也必须通过对网络行为的观察(如分组丢失与时延)来推断。 TCP采用端到端的方法解决拥塞控制,因为IP层不会向端系统提供有关网络拥塞的反馈信息。 TCP报文段的丢失(通过超时或3 次冗余确认而得知)被认为是网络拥塞的一个迹象, TCP会相应地减小其窗口长度。 我们还将看到关于TCP拥塞控制的一些最新建议,即使用增加的往返时延值作为网络拥塞程度增加的指示。
- 网络辅助的拥塞控制。在网络辅助的拥塞控制中,路由器向发送方提供关于网络中拥塞状态的显式反馈信息。 这种反馈可以简单地用一个比特来指示链路中的拥塞情况。
默认因特网版本的 IP 和TCP 采用端到端拥塞控制方法。对于网络辅助的拥塞控制,拥塞信息从网络反馈到发送方通常有两种方式,如图所示。直接反馈信息可以由网络路由器发给发送方。更为通用的第二种形式的通知是,路由器标记从发送方流向接收方的分组中的某个字段来指示拥塞是否产生,收到一个标记的分组后,接收方就会向发送方通知该网络拥塞指示: 注意到后一种形式的通知至少要经过一个完整的往返时间。

TCP拥塞控制
TCP的另一个关键部分就是其拥塞控制机制。TCP使用端到端拥塞控制而不是使网络辅助的拥塞控制。因为 IP层不向端系统提供显式的网络拥塞反馈。
TCP 所采用的方法是让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率。 如果一个TCP发送方感知从它到目的地之间的路径上没什么拥塞, 则TCP发送方增加其发送速率;如果发送方感知沿着该路径有拥塞, 则发送方就会降低其发送速率。 但是这种方法提出了三个问题。第一, 一个TCP发送方如何限制它向其连接发送流量的速率呢?第二, 一个TCP发送方如何感知从它到目的地之间的路径上存在拥塞呢?第三,当发送方感知到端到端的拥塞时,采用何种算法来改变其发送速率呢?
首先分析一下TCP发送方是如何限制向其连接发送流量的。之前,我们看到, TCP 连接的每一端都是由一个接收缓存、 一个发送缓存和几个变量组成。 运行在发送方的 TCP 拥塞控制机制跟踪一个额外的变量,即拥塞窗口(cwnd)。它对一个 TCP 发送方能向网络中发送流量的
速率进行了限制。 特别是,在一个发送方中未被确认的数据量不会超过cwnd 与 rwnd 中的最小值
L a s t B y t e S e n t − L a s t B y t e A c k e d ≤ m i n ∣ c w n d , r w n d ∣ LastByteSent - LastByteAcked≤min | cwnd, rwnd | LastByteSent−LastByteAcked≤min∣cwnd,rwnd∣
假设TCP接收缓存rwnd足够大,以至可以忽略接收窗口的限制;因此在发送方中未被确认的数据量仅受限于 rwnd。还假设发送方总是有数据要发送,即在拥塞窗口中的所有报文段要被发送。
上述公式约束了发送方未被确认分组的数据量小于等于cwnd,因此间接地限制发送方的发送速率。 为了理解这一点,我们来考虑一个丢包和发送时延均可以忽略不计的连接。因此粗略地讲,在每个往返时间 (RTT)的起始点(发送时),上面的限制条件允许发送方向该连接发送cwnd个字节的数据,在该RTT结束时发送方接收对数据的确认报文。因此,该发送方的发送速率大概是cwndl/RTT 字节/秒。 通过调节 cwnd 的值,发送方因此能调整它向连接发送数据的速率。
我们接下来考虑第二个问题。TCP发送方是如何感知在它与目的地之间的路径上出现了拥塞的。我们将一个TCP发送方的"丢包事件"定义为:要么出现超时, 要么收到来自接收方的 3个冗余ACK。当出现过度的拥塞时, 在沿着这条路径上的一台(或多台)路由器的缓存会溢出,引起一个数据报(包含一个TCP报文段) 被丢弃。丢弃的数据报接着会引起发送方的丢包事件(要么超时或收到3个冗余ACK) , 发送方就认为在发送方到接收方的路径上出现了拥塞的指示。
考虑了拥塞检测问题后,我们接下来考虑网络没有拥塞这种更为乐观的情况,即没有出现丢包事件的清况。 在此情况下,在TCP 的发送方将收到对于以前未确认报文段的确认。 TCP将这些确认的到达作为一切正常的指示,即在网络上传输的报文段正被成功地交付给目的地,并增加窗口的长度。 注意到如果确认以相当慢的速率到达,则该窗口将以相当慢的速率增加。
通过调节cwnd 值以控制发送速率的机制,关键的问题依然存在: TCP发送方怎样确定它应当发送的速率呢?如果众多TCP发送方总体上发送太快,它们能够拥塞网络。然而,如果 TCP发送方过于谨慎,发送太慢,它们不能充分利用网络的带宽; 那么TCP发送方如何确定它们的发送速率,既使得网络不会拥塞,与此同时又能充分利用所有可用的带宽?TCP发送方是显式地协作,或存在一种分布式方法使TCP发送方能够仅基于本地信息设置它们的发送速率?TCP使用下列指导性原则回答这些问题;
- 一个丢失的报文段表意味着拥塞,因此当丢失报文段时应当降低TCP发送方的速率。
- 一个确认报文段指示该网络正在顺利地向接收方交付报文段,能够增加发送方的速率,窗口长度因此能够增加。
- 带宽探测。收到ACK表示源到目的地路径无拥塞,而丢包事件表示路径拥塞。TCP 调节其传输速率的策略是先增加传输速率, 除非出现
丢包事件,此时才减小传输速率。
TCP 拥塞控制算法包括 3 个主要部分:1.慢启动;2.拥塞避免;3.快速恢复。 慢启动和拥塞避免是TCP 的强制部分, 快速恢复是推荐部分,对TCP发送方并非是必需的。
- 慢启动
当一条TCP连接开始时, cwnd 的值通常初始置为一个 MSS。这就使得初始发送速率大约为 MSS/RTT。 例如,如果 MSS =500 字节且 RTT=200ms,则得到的初始发送速率大约只有20kbps。 对TCP 发送方而言,可用带宽可能比 MSS/RTT 大得多, TCP 发送方希望迅速找到可用带宽的量。 因此,在慢启动状态, cwnd 的值以 1 个 MSS 开始并且每当传输的报文段首次被确认就增加1个MSS。

如上图所示例子,TCP 向网络发送第一个报文段并等待一个确认。 当该确认到达时, TCP 发送方将拥塞窗口增加一个MSS, 并发送出两个最大长度的报文段。 这两个报文段被确认,则发送方对每个确认报文段将拥塞窗口增加一个MSS, 使得拥塞窗口变为4 个MSS, 并这样下去。 这一过程每过一个RTT, 发送速率就翻番。 因此, TCP发送速率起始慢,但在慢启动阶段以指数增长。但是,何时结束这种指数增长呢?慢启动对这个问题提供了几种答案。
- 首先,如果发生一个由超时指示的丢包事件,TCP 发送方将 cwnd设置为 1 并重新开始慢启动过程。
- 第二种方式是当检测到拥塞时,直接将窗口设置为当前的一半,并结束慢启动 且 TCP转移到拥塞避免模式。
- 最后一种结束慢启动的方式是,如果检测到3 个冗余ACK, 这时 TCP执行一种快速重传并进入快速恢复状态。
- 拥塞避免
一旦进入拥塞避免状态, cwnd 的值大约是上次遇到拥塞时的值的一半,且距离拥塞可能并不遥远。因此, TCP无法每过一个RTT再将 cwnd 的值翻番,而是采用了一种较为保守的方法,每个RTT只将cwnd 的值增加一个MSS 。这能够以几种方式完成。 一种通用的方法是对于TCP发送方无论何时到达一个新的确认,就将cwnd增加一个 MSS*MSS/cwnd 字节大小。
但是何时结束拥塞避免状态下的窗口线性增长?
- 当出现超时(指示出现了丢包事件), cwnd 的值被设置为 1 个MSS.
- 发送方接收到3个冗余ACK指示出现了丢包事件,将cwnd 的值减半,进入快速恢复状态。
-
快速恢复
在快速恢复中,对于引起TCP进入快速恢复状态的缺失报文段,每收到一个冗余的ACK, cwnd 的值增加一个 MSS。最终,当对之前丢包的报文段ACK 到达时, TCP 降低cwnd 后进入拥塞避免状态。 如果出现超时事件, cwnd 的值被设置为 1 个MSS,且进入慢启动状态。如果出现丢包事件,cwnd设置为一半。
-
TCP 拥塞控制: 回顾
在了解慢启动、拥塞避免和快速恢复的细节后, 现在有必要退回来回顾一下全局。 忽略一条连接开始时初始的慢启动阶段,假定丢包由 3 个冗余的ACK而不是超时指示, TCP 的拥塞控制是:每个 RTT 内 cwnd 线性增加 lMSS, 然后出现3 个冗余CK 事件时 cwnd 减半。因此, TCP 拥塞控制常常被称为加性增、乘性减(AIMD)拥塞控制方式。

AIMD 拥塞控制引 发了上图中所示的"锯齿"行为、 这也很好地表示了TCP 检测带宽时,线性地增加它的拥塞窗门长度(因此增加其传输速率),直到出现3 个冗余 ACK 事件,然后减半长度,然后又开始了线性增长, 探测是否还有另外的可用带宽。
-
对 TCP 吞吐量的宏观描述
给出 TCP 的锯齿状行为后, 自然要考虑一个长存活期的 TCP连接的平均吞吐量(即平均速率)可能是多少。在这个分析中,我们将忽略在超时事件后出现的慢启动阶段( 这些阶段通常非常短,因为发送方很快就以指数增长离开该阶段 ) 。与窗口长度是W字节,且当前往返时间是RTT秒时, 则TCP 的发送速率大约是W/RTT。 于是, TCP通过每经过 1 个RTT ,将 W增加 1 个MSS探测出额外的带宽,直到一个丢包事件发生为止。当一个丢包事件发生时,窗口长度减半。假设在连接持续期间 RTT,那么TCP的传输速率在W/(2 x RTT) 到 W/RTT之间变化。
当速率增长至W/RTT时,网络丢弃来自连接的分组; 然后发送速率就会减半,进而每过一个 RTT,发送速率增加MSS/ RTT, 直到再次达到 W/RTT 为止。 这一过程不断地自我重复。所以我们可以通过理想化的TCP稳态动态性模型,推出一个将连接的丢包率与可用带宽联系起来的有趣表达式

公平性
考虑k条TCP连接,每条都有不同的端到端路径,但是都经过一段传输速率为R bps 的瓶颈链路。 (所谓瓶颈链路,是指对于每条连接, 沿着该连接路径上的所有其他段链路都不拥塞. 而且与该瓶颈链路的传输容佩相比, 它们都有充足的传输容量。)假设每条连接都在传输一个大文件,而且无 UDP流量通过该段瓶颈链路。 如果每条连接的平均传输速率接近R/K, 即每条连接都得到相同份额的链路带宽, 则认为该拥塞控制机制是公平的。
TCP 的 AIMD 算法公平吗?尤其是假定可在不同时间启动并因此在某个给定的时间点可能具有不同的窗口长度情况下, 对这些不同的TCP 连接还是公平的吗? TCP 趋于在竞争的多条TCP 连接之间提供对一段瓶颈链路带宽的平等分享。
我们考虑有两条TCP连接共享一段传输速率为 R的链路的简单例子,如图所示。

我们将假设这两条连接有相同的MSS 和 RTT,它们有大量的数据要发送,且没有其他TCP连接或 UDP数据报穿越该段共享链路。 我们还
将忽略TCP 的慢启动阶段。这两条TCP连接理想情况是,两个吞吐量的和应等于R。

所以我们的目标应该是使取得的吞吐量落在平等带宽共享曲线与全带宽利用曲线的交叉点附近的某处。假定TCP窗口长度是这样的, 即在某给定时刻. 连接1 和连接2实现了图中A点所指明的吞吐量,此时这两条连接共同消耗的链路带宽量小于R, 所以无丢包事件发生, 根据TCP 的拥塞避免算法的结果,这两条连接每过一个 R'IT都要将其窗口增加 1 个MSS。 因此, 这两条连接的总吞吐量就会逐步增长。最终, 这两条连接共同消耗的带宽将超过R, 最终将发生分组丢失。假设连接 1和连接2 实现B点指明的吞吐量时,共同消耗带宽超过了R,所以它们都经历了分组丢失。于是就按二分之一减小其窗口,到达了C点。因为在C点,共同消耗的带宽小于R, 所以这两条连接再次增加其吞吐量。最终,再次发生丢包事件,达到了D点。所以,这两条连接实现的带宽最终将沿着平等带宽共享曲线在波动。
公平性和UDP
我们刚才已经看到, TCP拥塞控制是如何通过拥塞窗口机制来调节一个应用程序的传输速率的。 许多多媒体应用如因特网电话和视频会议. 经常就因为这种特定原因而不在TCP 上运行,因为它们不想其传输速率被扼制,即使在网络非常拥塞的情况下。这些应用宁可在UDP上运行, UDP是没有内置的拥塞控制的。当运行在 UDP上时,这些应用能够以恒定的速率将其音频和视频数据注入网络之中并且偶尔会丢失分组, 而不愿在拥塞时将其发送速率降至公平级别并且不丢失任何分组。从TCP 的观点来看,运行在UDP 上的多媒体应用是不公平的,因为它们不与其他连接合作,也不适时地调整其传输速率。 因为TCP拥塞控制在面临拥塞增加(丢包)时,将降低其传输速率,而 UDP源则不必这样做, UDP源有可能压制 TCP 流量。
公平性和并行TCP连接
即使我们能够迫使UDP流僵具有公平的行为,但公平性问题仍然没有完全解决。 这是因为我们没有什么办法阻止基于TCP的应用使用多个并行连接。 例如, Web浏览器通常使用多个并行TCP连接来接收一个Web页中的多个对象。当一个应用使用多条并行连接时,它占用了一条链路中较大比例的带宽。举例来说,考虑一段速率为R且支待9个在线客户-服务器应用的链路,每个应用使用一条TCP连接。 如果一个新的应用加入进来,也使用一条TCP连接,则每个应用得到差不多相同的传输速率R/10。 但是如果这个新的应用这次使用了 11个并行TCP连接,则这个新应用就不公平地分到 R* 11/20 的带宽。
明确拥塞通告:网络辅助拥塞控制
之前我们学习到一个TCP发送方不会收到来自网络层的明确拥塞指示,而是通过观察分组丢失来推断拥塞。 但实际上对于IP 和TCP 的扩展方案 已经提出并已经实现和部署,该方案允许网络明确向 TCP发送方和接收方发出拥塞信号。 这种形式的网络辅助拥塞控制称为明确拥塞通告。如图所示,涉及了 TCP 和 IP 协议。

在网络层, IP数据报首部的服务类型字段中的两个比特被用于ECN。 路由器所使用的一种 ECN 比特设置指示该路由器正在历经拥塞。 该拥塞指示则由被标记的IP数据报所携带,送给目的主机,再由目的主机通知发送主机。当接收主机中的TCP接收到的数据报指示了ECN拥塞,在接收方到发送方的TCP ACK报文段中设置 ECE (明确拥塞通告回显)比特,通知发送主机。 接下来,TCP 发送方通过减半拥塞窗口做出反应。
参考目录
书籍:《计算机网络:自顶向下方法(第七版)》