计算机网络 第三章:运输层(三)

发布于:2025-05-24 ⋅ 阅读:(15) ⋅ 点赞:(0)

3.5.5 流量控制

        一条 TCP 连接的每一侧主机都为该连接设置了接收缓存。当该 TCP 连接收到正确、按序的字节后,它就将数据放入接收缓存。相关联的应用进程会从该缓存中读取数据,但不必是数据刚一到达就立刻读取。事实上,接收方应用也许正忙于其他任务,甚至要过很长时间后才去读取该数据。如果某应用程序读取数据时相对缓慢,而发送方发送得太多、太快,发送的数据就会很容易地使该连接的接收缓存溢出

         TCP 为它的应用程序提供了流量控制服务( flow-control service) 以消除发送方使接收方缓存溢出的可能性。流量控制因此是一个速度匹配服务,即发送方的发送速率接收方应用程序的读取速率相匹配。前面提到过,TCP 发送方也可能因为 IP 网络的拥塞而被遏制;这种形式的发送方的控制被称为拥塞控制 (congeslion control) ,即使流量控制拥塞控制采取的动作非常相似(对发送方的遏制),但是它们显然是针对完全不同的原因而采取的措施。现在讨论 TCP 如何提供流量控制服务的。为了能从整体上看问题,在本节都假设 TCP 是这样实现的,即 TCP 接收方丢弃失序的报文段

         TCP 通过让发送方维护一个称为接收窗口(receive window)的变量来提供流量控制。通俗地说,接收窗口用于给发送方一个指示一一该接收方还有多少可用的缓存空间。因为 TCP 是全双工通信在连接两端的发送方都各自维护一个接收窗口。在文件传输的情况下研究接收窗口。假设主机A 通过一条 TCP 连接向主机B 发送一个大文件。主机 B为该连接分配了一个接收缓存,并用RcvBuffer 来表示其大小。主机B 上的应用进程不时地从该缓存中读取数据。定义以下变量。

        LastByteRead:主机 B 上的应用进程从缓存读出的数据流的最后一个字节的编号。

        LastByteRcvd:从网络中到达的并且已放入主机 B 接收缓存中的数据流的最后一个字节的编号。

        由于 TCP 不允许已分配的缓存溢出,下式必须成立:

                        LastByteRcvd-LastByteRead\leqslant RcvBuffer

        接收窗口用 rwnd 表示,根据缓存可用空间的数量来设置:

                        rwnd=RcvBuffer-[LastByteRcvd-LastByteRead] 

        由于该空间是随着时间变化的,所以 rwnd 是动态的。图 3-38 对变量 rwnd 进行图示

        连接是如何使用变量 rwnd 来提供流量控制服务的?主机 B 通过把当前的 rwnd 值放入它发给主机 A 的报文段接收窗口字段中,通知主机 A 它在该连接的缓存中还有多少可用空间。开始时,主机 B 设定 rwnd=RcvBuffer,主机 B 必须跟踪几个与连接有关的变量。

        主机 A 轮流跟踪两个变量, LastByteSent 和 LastByteAcked ,这两个变量的意义很明显注意到这两个变量之间的差 LastByteSent - LastByteAcked ,就是主机 A 发送到连接中但未被确认的数据量。通过将未确认的数据量控制在值 rwnd 以内,就可以保证主机 A 不会使主机 B 的接收缓存溢出。因此,主机 A 在该连接的整个生命周期须保证:

                        LastByteSent-LastByteAcked \leq rwnd 

         对于这个方案还存在一个小小的技术问题。为了理解这一点,假设主机 B 的接收缓存已经存满,使得 rwnd =0 。在将 rwnd =0 通告给主机 A 之后,还要假设主机 B 没有任何数据要发给主机 A。此时,考虑会发生什么情况。因为主机 B 上的应用进程将缓存清空,TCP 并不向主机 A 发送带有 rwnd 新值的新报文段;事实上,TCP 仅当在它有数据或有确认要发时才会发送报文段给主机 A 。这样,主机 A 不可能知道主机 B 的接收缓存已经有新的空间了,即主机 A 被阻塞而不能再发送数据!为了解决这个问题,TCP 规范中要求:当主机 B 的接收窗口为 0 时,主机 A 继续发送只有一个字节数据的报文段这些报文段将会被接收方确认最终缓存将开始清空,并且确认报文里将包含一个非 0 的rwnd 值

3.5.6 TCP 连接管理

         观察如何建立和拆除一条 TCP 连接。假设允许在一台主机(客户)上的一个进程想与另一台主机(服务器)上的一个进程建立一条连接。客户应用进程首先通知客户 TCP,它想建立一个与服务器上某个进程之间的连接。客户中的 TCP 会用以下方式与服务器中的 TCP 建立一条 TCP 连接:

        第一步:客户端的 TCP 首先向服务器端的 TCP 发送一个特殊的 TCP 报文段。该报文段中不包含应用层数据。但是在报文段的首部(参见图 3-29)中的一个标志位(即 SYN 比特)被置为 1。因此,这个特殊报文段被称为 SYN 报文段。另外,客户会随机地选择一个初始序号(client_isn),并将此编号放置于该起始的 TCP SYN 报文段的序号字段中。该报文段会被封装在一个 lP 数据报中,并发送给服务器。为了避免某些安全性攻击,在适当地随机化选择 client_isn 方面有许多研究。

        第二步: 一旦包含 TCP SYN 报文段的 IP 数据报到达服务器主机(假定它的确到达了!),服务器会从该数据报中提取出 TCP SYN 报文段,为该 TCP 连接分配 TCP 缓存和变量,并向该客户 TCP 发送允许连接的报文段。(将在第 8 章看到,在完成三次握手的第三步之前分配这些缓存和变量,使得 TCP 易于受到称为 SYN 洪泛的拒绝服务攻击。)这个允许连接的报文段也不包含应用层数据。但是,在报文段的首部却包含 3个重要的信息。首先, SYN 比特被置为 1。其次,该 TCP 报文段首部的确认号字段被置为 client _ isn +1。最后,服务器选择自己的初始序号(server_isn) ,并将其放置到 TCP 报文段首部的序号字段中。这个允许连接的报文段实际上表明了:" 我收到了你发起建立连接的 SYN 分组,该分组带有初始序号client_isn。我同意建立该连接,我自己的初始序号是 sewer_isn  "该允许连接的报文段被称为 SYNACK 报文段 (SYNACK segment)。

         第三步:在收到 SYNACK 报文段后,客户也要给该连接分配缓存和变量。客户主机则向服务器发送另外一个报文段;这最后一个报文段对服务器的允许连接的报文段进行了确认(该客户通过将值 server_isn+1 放置到 TCP 报文段首部的确认字段中来完成此项工作)因为连接已经建立了,所以该 SYN 比特被置为 0。 该三次握手的第三个阶段可以在报文段负载中携带客户到服务器的数据。

         一旦完成这 3 个步骤,客户和服务器主机就可以相互发送包括数据的报文段了。在以后每一个报文段中, SYN 比特都将被置为 0。注意到为了创建该连接,在两台主机之间发送了 3 个分组,如图 3-39 所示。由于这个原因,这种连接创建过程通常被称为3 次握手 (three-way handshake) 。注意到这样一件事是很有趣的, 一个攀岩者和一个保护者(他位于攀岩者的下面,他的任务是处理好攀岩者的安全绳索)就使用了与 TCP 相同的 3 次握手通信协议,以确保在攀岩者开始攀爬前双方都已经准备好了。

        参与一条 TCP 连接的两个进程中的任何一个都能终止该连接。当连接结束后,主机中的 “ 资源 ”(即缓存和变量)将被释放。举一个例子,假设某客户打算关闭连接,如图 3-40 所示。客户应用进程发出一个关闭连接命令。这会引起客户 TCP 向服务器进程发送一个特殊的报文段。这个特殊的报文段让其首部中的一个标志位(FIN 比特)被设置为 1。当服务器接收到该报文段后,就向发送方回送一个确认报文段。然后,服务器发送它自己的终止报文段,其 FIN 比特被置为 1。最后,该客户对这个服务器的终止报文段进行确认。此时,两台主机上用于连接的所有资源都被释放

         

        在一个 TCP 连接的生命周期内,允许在每台主机中的 TCP 协议在各种 TCP 状态之间变迁。图 3-41 说明了客户 TCP 会经历的一系列典型 TCP 状态。客户 TCP 开始时处于 CLOSED (关闭)状态。客户的应用程序发起一个新的 TCP 连接。这引起客户中的 TCP 向服务器中的 TCP 发送一个 SYN 报文段。在发送 SYN 报文段后,客户 TCP 进入了 SYN_SENT 状态。当客户 TCP 处在 SYN_SENT 状态时,它等待来自服务器 TCP 的对客户所发报文段进行确认且 SYN 比特被置为 1 的一个报文段。收到这样的报文段后,客户 TCP 进入 ESTABLISHED (已建立)状态。处在 ESTABLISHED 状态时,TCP 客户就能发送和接收包含有效载荷数据(即应用层产生的数据)的TCP 报文段

         假设客户应用程序决定要关闭该连接。(注意到服务器也能选择关闭该连接。)这引起客户 TCP 发送一个带有 FIN 比特被置为 1 的 TCP 报文段,并进入 FIN_WAIT_1 状态。当处FIN-WAIT_1 状态时,客户 TCP 等待 1 个来自服务器的带有确认的 TCP 报文段。当它收到该报文段时,客户 TCP 进入 FIN-WAIT_2 状态。当处在 FIN_WAIT_2 状态时,客户等待来自服务器的 FIN 比特被置为 1 的另一个报文段;当收到该报文段后,客户 TCP 对服务器的报文段进行确认,并进入 TIME_WAIT 状态。假定 ACK 丢失, TIME-WAIT 状态使 TCP客户重传最后的确认报文。在 TIME_WAIT 状态中所消耗的时间是与具体实现有关的,而典型的值是 30 秒、 1分钟或 2分钟。经过等待后,连接就正式关闭,客户端所有资源(包括端口号)将被释放。

        图 3-42 图示了服务器端的 TCP 通常要经历的一系列状态,其中假设客户开始连接拆除。 这些状态变迁是自解释的。在这两个状态变迁图中,只给出了 TCP 连接是如何正常地被建立和拆除

        上面的讨论假定了客户和服务器都准备通信,即服务器正在监听客户发送其 SYN 报文段的端口。考虑当一台主机接收到一个 TCP 报文段,其端口号或源 IP 地址与该主机上进行中的套接字不匹配的情况。例如,假如一台主机接收了具有目的端口 80 的一个 TCP SYN 分组,但该主机在端口 80 不接受该连接(即它不在端口 80 上运行 Web 服务器)。则该主机向源发送一个特殊重置报文段。该 TCP 报文段将 RST 标志位置为 1。因此,当主机发送一个重置报文段时,它告诉源“我没有那个报文段的套接字,请不要再发送该报文段了”。当一台主机接收一个 UDP 分组,它的目的端口与进行中的 UDP 套接字不匹配,该主机发送一个特殊的 ICMP 数据报

        既然我们已经对 TCP 连接管理有了深入的了解,我们再次回顾 nmap 端口扫描工具,并更为详细地研究它的工作原理。为了探索目标主机上的一个特定的 TCP 端口,如端口6789 , nmap 将对那台主机的目的端口 6789 发送一个特殊的 TCP SYN 报文段。有 3 种可能的输出: 

        ① 源主机从目标主机接收到一个 TCP SYNACK 报文段。因为这意味着在目标主机上一个应用程序使用 TCP 端口 6789 运行,nmap 返回“ 打开 ”。

        ② 源主机从目标主机接收到 一个 TCP RST 报文段 这意味着该 SYN 报文段到达了目标主机,但目标主机没有运行一个使用 TCP 端口 6789 的应用程序。但攻击者至少知道发向该主机端口 6789 的报文段没有被源和目标 机之间的任何防火墙所阻挡。

        ③ 源什么也没有收到。这很可能表明该 SYN 报文段被中间的防火墙所阻挡,无法到达目标主机。 

3.6 拥塞控制原理

         面临分组丢失时用于提供可靠数据传输服务的基本原理特定的 TCP 机制。在实践中,这种丢包一般是网络变得拥塞时由于路由器缓存溢出引起的。分组重传因此作为网络拥塞的征兆(某个特定的运输层报文段的丢失)来对待,但是却无法处理导致网络拥塞的原因,因为有太多的源想以过高的速率发送数据。为了处理网络拥塞原因,需要一些机制以在面临网络拥塞时遏制发送方

 3.6.1 拥塞原因与代价

        重点理解一个较为简单的问题,即随着主机增加其发送速率并使网络变得拥塞,会发生的情况。

        1. 情况1:两个发送方和一台具有无穷大缓存的路由器

        先考虑最简单的拥塞情况:两台主机(A 和 B)都有一条连接,且这两条连接共享源与目的地之间的单挑路由,如图 3-43 所示。

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

         图 3-44 描绘出了第一种情况下主机 A 的连接性能。左边的图形描绘了每连接的吞吐量( per- connection throughput) (接收方每秒接收的字节数)与该连接发送速率之间的函数关系。当发送速率在 0-R/2 之间时,接收方的吞吐量等于发送方的发送速率,即发送方发送的所有数据经有限时延后到达接收方。然而当发送速率超过 R/2 时,它的吞吐量只能达 R/2。这个吞吐量上限是由两条连接之间共享链路容量造成的。链路完全不能以超过R/2 的稳定状态速率向接收方交付分组。无论主机 A 和主机 B将其发送速率设置为多高,它们都不会看到超过 R/2 的吞吐量。

         取得每连接 R/2 的吞吐量实际上看起来可能是件好事,因为在将分组交付到目的地的过程中链路被充分利用。但是,图 3-44b 的图形却显示了以接近链路容量的速率运行时产生的后果。当发送速率接近 R/2 时(从左至右)平均时延就会越来越大。当发送速率超过 R/2 时,路由器中的平均排队分组数就会无限增长,源与目的地之间的平均时延也会变成无穷大(假设这些连接以此发送速率运行无限长时间并且有无限量的缓存可用)因此,虽然从吞吐量角度看,运行在总吞吐量接近R 的状态也许是一个理想状态,但从时延角度看,却远不是一个理想状态。甚至在这种(极端)理想化的情况中,我们已经发现了拥塞网络的一种代价,即当分组的到达这率接近链路容量时,分组经历巨大的排队时延

        2. 情况2:两个发送方和一台具有有限缓存的路由器

        现在我们从下列两个方面对情况 1 稍微做一些修改(参见图3-45)。 首先,假定路由器缓存的容量是有限的。这种现实世界的假设的结果是,当分组到达一个已满的缓存时会被丢弃。其次,我们假定每条连接都是可靠的。如果一个包含有运输层报文段的分组在路由器中被丢弃,那么它终将被发送方重传。由于分组可以被重传,所以我们现在必须更心地使用发送速率这个术语。特别是我们再次以 λin 字节/秒表示应用程序将初始数据发送到套接字中的速率运输层向网络中发送报文段(含有初始数据或重传数据)的速率用 λin' 字节/秒表示。λin' 有时被称为网络的供给载荷。

        在情况 2 下实现的性能强烈地依赖于重传的方式。首先,考虑一种不真实的情况,即主机 A 能够以某种方式确定路由器中的缓存是否空闲,因而仅当缓存空闲时才发送一个分组。在这种情况下,将不会产生丢包,λin 与 λin' 相等,并且连接的吞吐量就等于 λin。图 3-46a 中描述了该情况。从吞吐量的角度看,性能是理想的,即发送的每个分组都能被接收到。注意到在这种情况下,平均主机发送速率不能超过 R/2,因为假定不会发生分组丢失。

        接下来考虑一种更为真实的情况,发送方仅当在确定了一个分组已经丢失时才重传。(同样,所做的假设有一些弹性。然而,发送主机有可能将超时时间设置得足够长,以无形中使其确信一个还没有被确认的分组已经丢失。)在这种情况下,性能就可能与图 3-46b所示的情况相似。为了理解这时发生的情况,考虑一下供给载荷 λin' (初始数据传输加上重传的总速率)等于 R/2 的情况。根据图3-46b ,在这一供给载荷值时,数据被交付给接收方应用程序的速率是 R/3。因此,在所发送的 0.5R 单位数据当中,从平均的角度说,0.333R 字节/秒是初始数据,而 0.166R 字节/秒是重传数据。我们在此看到了另一种网络拥塞的代价,即发送方必须执行重传以补偿因为缓存溢出而丢弃(丢失)的分组。

         最后,我们考虑下面一种情况:发送方也许会提前发生超时并重传在队列中已被推迟但还未丢失的分组。在这种情况下,初始数据分组和重传分组都可能到达接收方。当然,接收方只需要一份这样的分组副本就行了,重传分组将被丢弃。在这种情况下,路由器转发重传的初始分组副本是在做无用功,因为接收方已收到了该分组的初始版本。而路由器本可以利用链路的传输能力去发送另一个分组。这里 ,我们又看到了网络拥塞的另一种代价,即发送方在遇到大时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本。图 3-46c 显示了当假定每个分组被路由器转发(平均)两次时,吞吐量与供给载荷的对比情况。由于每个分组被转发两次,当其供给载荷接近 R/2 时,其吞吐量将渐近 R/4

 

        3. 情况3:4 个 发送方和具有有限缓存的多台路由器及多跳路径

         在最后一种拥塞情况中,有 4 台主机发送分组,每台都通过交叠的两跳路径传输,如图 3-47 所示。再次假设每台主机都采用超时 / 重传机制来实现可靠数据传输服务,所有的主机都有相同的 λin 值,所有路由器的链路容量都是 R 字节/秒

         考虑从主机 A 到主机 C 的连接,该连接经过路由器 R1 和 R2。A-C 连接与 D-B连接共享路由器 R1 ,并与 B-D 连接共享路由器 R2。对极小的 λin 值,路由器缓存的溢出是很少见的(与拥塞情况 1、拥塞情况 2 中的一样) ,吞吐量大致接近供给载荷。对稍大的 λin 值,对应的吞吐量也更大,因为有更多的初始数据被发送到网络中并交付到目的地,溢出仍然很少。因此,对于较小的 λin,λin增大会导致 λout 的增大

         在考虑了流量很小的情况后,下面分析当 λin (因此 λin')很大时的情况。考虑路由器 R2 不管 λin 的值是多大,到达路由器 R2 的 A~C 流量(在经过路由器 R1 转发后到达路由器R2)的到达速率至多是 R, 也就是从 R1到 R2 的链路容量。如果 λin' 对于所有连接(包括 B-D 连接)来说是极大的值,那么在R2 上, B-D 流量的到达速率可能会比 A-C流量的到达速率大得多。因为 A-C 流量与 B-D 流量在路由器 R2 上必须为有限缓存空间而竞争,所以当来自 B-D 连接的供给载荷越来越大时,A-C 连接上成功通过 R2(即由于缓存溢出而未被丢失)的流量会越来越小。在极限情况下,当供给载荷趋近于无穷大时,R2 的空闲缓存会立即被 B-D 连接的分组占满,因而 A-C 连接在 R2 上的吞吐量趋近于 0。这又一次说明在重载的极限情况下,A-C 端到端吞吐量将趋近于 0。引发了供给载荷与吞吐量之间的权衡,如图 3-48 所示。

 

        当考虑由网络所做的浪费掉的工作量时,随着供给载荷的增加而使吞吐量最终减少的原因是明显的。在上面提到的大流量的情况中,每当有一个分组在第二跳路由器上被丢弃时,第一跳路由器所做的将分组转发到第二跳路由器的工作就是“劳而无功”的。如果第一跳路由器只是丢弃该分组并保持空闲,则网络中的情况是幸运的(更准确的说是糟糕的)。需要指出的是,第一跳路由器所使用的将分组转发到第二跳路由器的传输容量用来传送不同的分组可能更有效益。(例如,当选择一个分组发送时,路由器最好优先考虑那些已经历过一定数量的上游路由器的分组)所以,在此又看到了由于拥塞而丢弃分组的另一种代价,即当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了

3.6.2 拥塞控制方法

        这里指出在实践中采用的两种主要拥塞控制方法,讨论特定的网络体系结构和具体使用这些方法的拥塞控制协议。

        在最为宽泛的级别上,可根据网络层是否为运输层拥塞控制提供了显示帮助,来区分拥塞控制方法。

        ① 端到端拥塞控制。在端到端拥塞控制方法中,网络层没有为运输层拥塞控制提供显式支持。即使网络中存在拥塞,端系统也必须通过对网络行为的观察(如分组丢失与时延)来推断之。将在 3.7.1 节中将看到, TCP 采用端到端的方法解决拥塞控制,因为 IP 层不会向端系统提供有关网络拥寨的反馈信息。TCP 报文段的丢失(通过超时或 3 次冗余确认而得知)被认为是网络拥塞的一个迹象, TCP 会相应地减小其窗口长度。我们还将看到关于 'TCP 拥塞控制的一些最新建议,即使用增加的往返时延值作为网络拙塞程度增加的指示。 

         ② 网络辅助的拥塞控制。在网络辅助的拥塞控制中,路由器向发送方提供关于网络中拥塞状态的显式反馈信息。这种反馈可以简单地用一个比特来指示链路中的拥塞情况。该方法在早期的 IBM SNA [Sehwartz 1982 ]、 DEC DECnet [Jain 1989 ; Ramakrishnan 1990 ]和 TM [Bluek 1995 ]等体系结构中被采用。更复杂的网络反馈也是可能的。例如,在 ATM 可用比特率( A vailable Bile Rate , ABR) 拥塞控制中,路由器显式地通知发送方它(路由器)能在输出链路上支持的最大主机发
送速率
。如上面所提到的,默认因特网版本的 IP TCP 采用端到端拥塞控制方法。然而,在 3.7.2 节中将看到,最近 IP 和 TCP 也能够选择性地实现网络辅助拥塞控制。

        对于网络辅助的拥塞控制,拥塞信息从网络反馈到发送方通常由两种方式,如图3-49所示。直接反馈信息可以由网络路由器发给发送方。这种方式的通知通常采用了一种阻塞分组的形式(主要是说:“ 我拥塞了!”)。更为通用的第二种形式的通知是路由器标记或更新从发送方流向接收方的分组中的某个字段来指示拥塞的产生。一旦收到一个标记的分组后,接收方就会向发送方通知该网络拥塞指示。注意到后一种形式的通知至少要经过一个完整的往返时间。 

3.7 TCP 拥塞控制

         TCP 为运行在不同主机上的两个进程之间提供了可靠传输服务。TCP 另一个关键部分就是拥塞控制机制。如在前一节指出,TCP 必须使用端到端拥塞控制不是网络辅助的拥塞控制,因为 IP 层不向端系统提供显式的网络拥塞反馈

         TCP 所采用的方法是让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率。如果 TCP 发送方感知从它到目的地之间的路径上没什么拥塞,则 TCP 发送方增加其发送速率;如果发送方感知沿着该路径有拥塞,则发送方就会降低其发送速率。但是这种方法提出了三个问题。第一,一个 TCP 发送方如何限制它向其连接发送流量的速率呢?第二 ,一个 TCP 发送方如何感知从它到目的地之间的路径上存在拥塞呢?第三 ,当发送方感知到端到端的拥塞时,采用何种算法来改变发送速率呢?

        ① TCP 发送方是如何限制向其连接发送流量的。

        3.5 节中,TCP 连接的每一端都是由一个接收缓存、一个发送缓存和几个变量(LastByteRead rwnd等)组成。运行在发送方的 TCP 拥塞控制机制跟踪一个额外变量,即 拥塞窗口。表示为 cwnd,它对一个 TCP 发送方能向网络中发送流量的速率进行了限制。特别的是,在一个发送方未被确认的数据量不会超过 cwnd 和 rwnd 的最小值

                 LastByteSent-LastByteAcked\leq min(cwnd,rwnd)

         为了关注拥塞控制(与流量控制形成对比) ,后面假设 TCP 接收缓存足够大,以至可以忽略接收窗口的限制;因此在发送方中未被确认的数据量仅受限于 cwnd。还假设发送方总是有数据要发送,即在拥塞窗口中的所有报文段要被发送。

         上面的约束限制了发送方中未被确认的数据量,因此间接地限制了发送方的发送速率。为了理解这一点,考虑一个丢包和发送时延均可以忽略不计的连接!因此粗略地讲,在每个往返时间(RTT)的起始点,上面的限制条件允许发送方向该连接发送 cwnd个字节的数据,在该 RTT 结束时发送方接收对数据的确认报文。因此,该发送方的发送速率大概是 cwnd/RTT 字节/秒。通过调节 cwnd 的值,发送方因此能调整它向连接发送数据的速率

         ② TCP 发送方如何感知在它与目的地之间的路径上出现了拥塞。

        将一个 TCP 发送方的"丢包事件"定义为:要么出现超时,要么收到来自接收方的 3个冗余 ACK。(回想在 3.5.4 节有关图二3-33 中的超时事件的讨论和收到 3   个冗余 AC后包括快速重传的后继修改 )。当出现过度的拥塞时,在沿着这条路径上的一台(或多台)路由器的缓存会溢出,引起一个数据报(包含 一个 TCP 报文段)被丢弃。丢弃的数据报接着会引起发送方的丢包事件(要么超时或收到三个冗余 ACK),发送方就认为在发送方到接收方的路径上出现了拥塞的指示。

         考虑没有拥塞的情况,没有出现丢包的情况。在 TCP 的发送方将收到对于以前未确认报文段的确认。如我们将看到的那样, TCP 将这些确认的到达作为一切正常的指示,即在网络上传输的报文段正被成功地交付给目的地,并使用确认来增加窗口的长度(及其传输速率)。注意到如果确认以相当慢的速率到达(例如,如果该端到端路径具有高时延或包含一段低带宽链路),则该拥塞窗口将以相当慢的速率增加。在另一方面,如果确认以高速率到达,则该拥塞窗口将会更为迅速地增大。因为 TCP 使用确认来触发(或计时)增大它的拥塞窗口长度, TCP 被说成是自计时( self- clocking)的

        ③ 改变发送速率

        给定调节 cwnd 值以控制发送速率的机制,关键的问题依然存在:TCP 发送方怎样确定它应当发送的速率呢?如果众多 TCP 发送方总体上发送太快,它们能够拥塞网络,导致在图 3-48 中看到的拥塞崩溃。事实上,为了应对在较早 TCP 版本下观察到的因特网拥塞崩溃,研发了该版本的 TCP。然而,如果 TCP发送方过于谨慎,发送太慢,它们不能充分利用网络的带宽;这就是说, TCP 发送方能够以更高的速率发送而不会使网络拥塞。那么 TCP 发送方如何确定它们的发送速率,既使得网络不会拥塞,与此同时又能充分利用所有可用的带宽?TCP 发送方是显式地协作,或存在一种分布式方法使 TCP 发送方能够仅基于本地信息设置它们的发送速率?TCP 使用下列指导性原则回答这些问题: 

         1.一个丢失的报文段表意味着拥塞,因此当丢失报文段时应当降低 TCP 发送方的速率。回想在 3.5.4 节中的讨论,对于给定报文段,一个超时事件或四个确认(一个初始 ACK 和其后的 3 个冗余 ACK) 被解释为跟随该四个 ACK 的报文段的"丢包事件"的一种隐含的指示。从拥塞控制的观点看,该问题是 TCP 发送方应当如何减小它的拥塞窗口长度,即减小其发送速率,以应对这种推测的丢包事件。

         2.一个确认报文段指示该网络正在向接收方交付发送方的报文段,因此,当对先前未确认报文段的确认到达时,能够增加发送方的速率。确认的到达被认为是一切顺利的隐含指示、即报文段正从发送方成功地交付给接收方 ,因此该网络不拥塞拥塞窗口长度因此能够增加。        

        3. 带宽探测。给定 ACK 指示源到目的地路径无拥塞,而丢包事件指示路径拥塞 TCP 调节其传输速率的策略是增加其速率以响应到达的 ACK ,除非出现丢包事件,此时才减小传输速率。因此,为探测拥塞开始出现的速率, TCP 发送方增加它的传输速率,从该速率后退,进而再次开始探测,看看拥塞开始速率是否发生了变化。TCP 发送方的行为也许类似于要求(并得到)越来越多糖果的孩子,直到最后告知他/她"不行!",孩子后退一点,然后过一会儿再次开始提出请求。注意到网络中没有明确的状态信令, ACK 和丢包事件充当了隐式信号,并且每个 TCP 发送方根据异步于其他 TCP 发送方的本地信息而行动。

         概述了 TCP 拥塞控制后,考虑 TCP 拥塞控制算法。该算法包括三个主要部分:①慢启动;②拥塞避免;③快速恢复。慢启动和拥塞避免是 TCP 的强制部分,两者的差异在于对收到的 ACK做出反应时增加 cwnd 长度的方式。将会看到慢启动比拥塞避免能更快地增 cwnd 的长度。快速恢复是推荐部分,对 TCP 发送方并非是必需的。

        1. 慢启动

         当一条 TCP 连接开始时, cwnd 的值通常初始置为 MSS 的较小值,这就使得初始发送速率大约为 MSS/RTT。例如,如果 MSS = 500 字节且 RTT 200 ms,则得到的初始发送速率大约只有 20kbps。由于对 TCP 发送方而言,可用带宽可能比 MSS/RTT 大得多, TCP 发送方希望迅速找到可用带宽的数量。因此,在慢启动( slow- start ) 状态, cwnd 的值以1个 MSS 开始并且每当传输的报文段首次被确认就增加 1个 MSS。在图 3-50 所示的例子中, TCP 向网络发送第一个报文段并等待一个确认。当该确认到达时, TCP 发送方将拥塞窗口增加 一个MSS,并发送出两个最大长度报文段。这两个报文段被确认,则发送方对每个确认报文段将拥塞窗口增加一个 MSS,使得拥塞窗口变为 4个 MSS,发送速率就翻番。因此,TCP 发送速率起始慢,但慢启动阶段以指数增长

         何时结束指数增长?慢启动给出几种答案。① 如果存在一个由超时指示的丢包事件(即拥塞),TCP 发送方将 cwnd 设置为 1 并重新开始慢启动过程。它还将第二个状态变量的值 ssthresh(慢启动阈值)设置为 cwnd/2,当检测到拥塞时将 ssthresh 置为拥塞窗口值的一半。② 当检测到拥塞时 ssthresh 设置为 cwnd 的一半,当到达或超过 ssthresh时,继续翻番 cwnd 有些鲁莽。因此,当 cwnd 的值等于 ssthresh 时,结束慢启动并且 TCP 转移到拥塞避免模式。当进入拥塞避免模式时,TCP 更为谨慎地增加 cwnd。③ 如果检测到 3个冗余 ACK,这时将执行快速重传并进入快速恢复状态。慢启动的 TCP 行为总结在 图 3-51 中的 TCP 拥塞控制的 FSM 描述中。

        2.拥塞避免

        一旦进入拥塞避免状态,cwnd 的值大约是上次遇到拥塞时的值的一半,即距离拥塞可能并不遥远!因此,TCP 无法每过一个 RTT 再将 cwnd  的值翻番,而是采用一种较为保守的方法,每个RTT 只将 cwnd 的值增加一个 MSS。这能够以几种方式完成。一种通用的方法是对于 TCP 发送方无论何时到达一个新的确认,就将 cwnd 增加一个 MSS(MSS/cwnd)字节。例如,如果 MSS 是 1460 字节 并且 cwnd 是 14600字节,则在一个 RTT 内发送 10 个报文段。每个到达 ACK(假定每个报文段一个 ACK)增加 1/10 MSS 的拥塞长度,因此在收到对所有10 个报文段的确定后,拥塞窗口的值将增加了一个 MSS。

        但是何时应当结束拥塞避免的线性增长(每 RTT 1 MSS) 呢?当出现超时时,TCP拥塞避免算法行为相同。与慢启动的情况一样, cwnd 的值被设置为 1个 MSS ,当丢包事件出现时, ssthresh 的值被更新为 cwnd 的值的一半。然而,前面讲过丢包事件也能由一个三个冗余 ACK 事件触发。 在这种情况下,网络继续从发送方向接收方交付报文段(就像由收到冗余 ACK 所指示的那样)因此 TCP 对这种丢包事件的行为,相比于超时指示的丢包,应当不那么剧烈:TCP cwnd 的值减半(为使测量结果更好,计及已收到的三个冗余的ACK 要加上 3个 MSS) ,并且当收到 3 个冗余的 ACK ,将 ssthresh 的值记录为 cwnd 的值的一半。接下来进入快速恢复状态

         3.快速恢复

         在快速恢复中,对于引起 TCP 进入快速恢复状态的缺失报文段,对收到的每个冗余的ACK , cwnd 的值增加一个 MSS。最终,当对丢失报文段的一个 ACK 到达时, TCP 在降低cwnd 后进入拥塞避免状态。如果出现超时事件,快速恢复在执行如同在慢启动和拥塞避免中相同的动作后,迁移到慢启动状态:丢包事件出现时, cwnd 的值被设置为 1个MSS ,并且 ssthres 的值设置为 cwnd 值的一半

        快速恢复是 TCP 推荐的而非必需的构件。 有趣的是,一种称为 TCP Tahoe 的 TCP 早期版本,不管是发生超时指示的丢包事件?还是发生三个冗余 ACK 指示的丢包事件,都无条件地将其拥塞窗口减 MSS ,并进入慢启动阶段 TCP 的较新版 TCP Reno ,则综合了快速恢复。

         图 3-52 图示了 Reno 版 TCP 与 Tahoe 版 TCP 的拥塞控制窗口的演化情况。在图中,阈值初始等于 8个 MSS。在前 8个传输回合,Tahoe 和 Reno 采取了相同的动作。拥塞窗口在慢启动阶段以指数速度快速爬升,并在第四轮传输时到达了阈值。然后拥塞窗口以线性速度爬升,在第八轮传输后出现 3 个冗余 ACK。注意到当该丢包时间发生时,拥塞窗口值为 12 MSS。于是 ssthresh 的值被设置为 6 MSS。在 TCP Reno 下,拥塞窗口被设置为 cwnd=9MSS,然后线性增长。在 TCP Tahoe 下,拥塞窗口被设置为 1个 MSS,然后呈指数增长,直至到达 ssthresh 值为止,在这个点开始线性增长。

        图 3-51 表示了 TCP 拥塞控制算法(慢启动、拥塞避免和快速恢复)的完整 FSM 描述。该图也指示了新报文段的传输或重传的报文段可能出现的位置。尽管区分 TCP 差错控制/重传与 TCP 拥塞控制非常重要,但是注意到 TCP 这两个方面交织链接的方式也很重要。

        4. TCP 拥塞控制:回顾

        在深入了解慢启动、拥塞避免和快速恢复的细节后,现在有必要退回来回顾一下全局。忽略一条连接开始时初始的慢启动阶段,假定丢包由 3个冗余的 ACK 而不是超时指示,TCP 的拥塞控制是:每个 RTT 内 cwnd 线性(加性)增加 lMSS ,然后出现 3 个冗余ACK 事件时 cwnd 减半(乘性减)。因此, TCP 拥塞控制常常被称为 加性增、乘性减( Additive- Increase , Multiplicative- Decrease , AIMD) 拥塞控制方式。AIMD 拥塞控制引发了在图 3-53 中所示的 “锯齿”行为,也很好图示了前面 TCP 检测带宽时的直觉,即 TCP 线性地增加它的拥塞窗口长度(因此增加其传输速率),直到出现 3 个冗余 ACK 事件。然后以 2 个因子来减少它的拥塞窗口长度,然后又开始了线性增长,探测是否还有另外的可用带宽。

         

        如前所述,许多 TCP 实现采用了 Reno 算法。Reno 算法的许多变种已被提出。TCP Vegas 算法试图在维持较好的吞吐量的同时避免拥塞。Vegas 的基本思想是:① 在分组丢失发生之前,在源与目的地之间检测路由器的拥塞② 当检测快要发生的分组丢失时,线性地降低发送速率。快要发生的分组丢失是通过观察 RTT 来预测的。分组的 RTT 越长,路由器中的拥塞越严重。

         5. 对 TCP 吞吐量的宏观描述

        给出 TCP 的锯齿状行为后,自然要考虑一个长存活期的 TCP 连接的平均吞吐量(即平均速率)可能是多少。在这个分析中,将忽略在超时事件后出现的慢启动阶段。(这些阶段通常非常短,因为发送方很快就以指数增民离开该阶段)在一个特定的往返问隔内, TCP 发送数据的速率是拥塞窗口与当前 RTT 的函数。当窗口长度是 w 字节,且当前往返时间是 RTT 秒时,则 TCP 的发送速率大约是 w/RTT。于是 TCP 通过每经过一个RTT 将 w 增加 1个 MSS 探测出额外的带宽,直到一个丢包事件发生为止。当一个丢包事件发生时,用 W 表示 w 的值。假设在连接持续期间 RTT 和 W 几乎不变,那么 TCP 的传输速率在 W/(2xRTT) 与 W/RIT 之间变化

         假设导出了 TCP 稳态行为的一个高度简化的宏观模型。当速率增长至 W/RTT 时,网络丢弃来自连接的分组;然后发送速率减半,进而每过一个 RTT 就发送速率增加 MSS/RTT,直到再次达到 W/RTT 为止。这一过程不断自我重复。因为 TCP吞吐量(速率)在两个极值之间线性增长,所以有:

        6. 经高带宽路径的 TCP

3.7.1 公平性

         考虑 K 条 TCP 连接,每条都有不同的端到端路径,但是都经过一段传输速率为 R bps 的瓶颈链路。(指对于每条连接,沿着该连接路径上的所有其他段链路都不拥塞,而且与该瓶颈链路的传输容量相比,他们都有充足的传输容量。)假设每条连接都在传输一个大文件,而且无 UDP 流量通过该瓶颈链路。如果每条连接的平均传输速率接近 R/K,即每条连接都得到相同份额的链路带宽,则认为该拥塞控制机制是公平的。

         TCP 的 AIMD 算法公平吗?尤其是假定可在不同时间启动并因此在某个给定的时间点可能具有不同的窗口长度情况下,对这些不同的 TCP 连接还是公平的吗? TCP 趋向于在竞争的多条 TCP 连接之间提供对一段瓶颈链路带宽的平等分享。其理由给出了很好的解释。

        考虑有两条 TCP 连接共享一段传输速率为 R 的链路的简单例子。如图 3-54 所示。将假设这两条连接有相同的 MSS 和 RTT(如果他们有相同的拥塞窗口长度,就会有相同的吞吐量),他们有大量的数据要发送,且没有其他 TCP 连接或 UDP 数据报穿越该段共享链路。还忽略 TCP 的慢启动阶段,并假设 TCP 连接一直按 CA 模式(AIMD)运行。 

        图 3-55 描绘了两条 TCP 连接实现的吞吐量情况。如果 TCP 要在这两条 TCP连接之间平等地共享链路带宽,那么实现的吞吐量曲线应当是从原点沿 45° 方向的箭头向外辐射(平等带宽共享)。理想情况是,两个吞吐量的和应等于 R。(当然,每条连接得到相同但容量为 0 的共享链路容量并非所期望的情况)所以目标应该是使取得的吞吐量落在图 3-55 中平等带宽共享曲线与全带宽利用曲线的交叉点附近某处

         

 

        1.公平性和UDP 

         刚才看到,TCP 拥塞控制是如何通过拥塞窗口机制来调节一个应用程序的传输速率的。许多多媒体应用如因特网电话和视频会议,经常就因为这种特定原因而不在 TCP 上运行,因为它们不想其传输速率被扼制,即使在网络非常拥塞的情况下。相反,这些应用宁可在 UDP 上运行, UDP 是没有内量的拥塞控制的。当运行在 UDP 上时,这些应用能够以恒定的速率将其音频和视频数据注入网络之中并且偶尔会丢失分组,而不愿在拥塞时将其发送速率降至"公平"级别并且不丢失任何分组。 TCP 的观点来看,运行在 UDP 上的多媒体应用是不公平的,因为它们不与其他连接合作,也不适时地调整其传输速率。因为 TCP 拥塞控制在面临拥塞增加(丢包)时,将降低其传输速率,而 UDP 源则不必这样做, UDP 源有可能压制 TCP 流量。当今的一个主要研究领域就是开发一种因特网中的拥塞控制机制,用于阻止 UDP 流量不断压制直至中断因特网吞吐量的情况。 

        2. 公平性和并行 TCP 连接

        即使我们能够迫使 UDP 流量具有公平的行为,但公平性问题仍然没有完全解决。这是因为我们没有什么办法阻止基于 TCP 的应用使用多个并行连接。例如, Web 浏览器通常使用多个并行 TCP 连接来传送一个 Web 页中的多个对象。(多条连接的确切数目可 以在多数浏览器中进行配置。)当一个应用使用多条并行连接时,它占用了一条拥塞链路中较大比例的带宽。举例来说,考虑一段速率为 R 且支持 9 个在线客户-服务器应用的链路,每个应用使用一条 TCP 连接,如果一个新的应用加入进来,也使用一条 TCP 连接, 则每个应用得到差不多相同的传输速率 R/10。但是如果这个新的应用这次使用了 10个并行 TC连接,则这个新应用就不公平地分到超过 R/2 的带宽。Web 流量在因特网中是非常普遍的,所以多条并行连接并非不常见。

3.7.2 明确拥塞通告:网络辅助拥塞控制

         一个 TCP 发送方不会收到来自网络层的明确拥塞指示,而是通过观察分组丢失来推断拥塞。最近,对于 IP 和 TCP 的扩展方案提出并已经实现和部署,该方案允许网络明确向 TCP 发送方和接收方发出拥塞信号。这种形式的网络辅助拥塞控制称为明确拥塞通告(ECN),如图3-56所示,涉及了 TCP 和 IP 协议。

 

        在网络层, IP 数据报首部的服务类型字段中的两个比特(总的说来,有四种可能的值)被用于 ECN。路由器所使用的一种 ECN 比特设置指示该路由器正在历经拥塞。该拥塞指示则由被标记的 IP 数据报所携带,送目的主机,再由目的主机通知发送主机,如图3-56 所示。RFC 3168 没有提供路由器拥塞时的定义;该判断是由路由器厂商所做的配置选择 ,并且由网络操作员决定。然而, RFC 3168 推荐仅当拥塞持续不断存在时才设置ECN 比特。发送主机所使用的另一种 ECN 比特设置通知路由器发送方和接收方是 ECN 使能的,因此能够对于 ECN 指示的网络拥塞采取行动。

         如图 3-56 所示,当接收主机中的 TCP 通过一个接收到的数据报收到了一个 ECN 拥塞指示时,接收主机中的 TCP 通过在接收方到发送方的 TCP ACK 报文段中设置 ECE (明确拥塞通告回显)比特(参见图 3- 29) ,通知发送主机中的 TCP 收到拥塞指示。接下来,TCP 发送方通过减半拥塞窗口对一个具有 ECE 拥塞指示的 ACK 做出反应。就像它对丢失报文段使用快速重传做出反应一样,并且在下一个传输的 TCP 发送方到接收方的报文段首部中对 CWR (拥塞窗口缩减)比特进行设置。    
    除了 TCP 以外的其他运输层协议也可以利用网络层发送 ECN 信号。数据报拥塞控制协议(DCCP)提供了一种低开销、控制拥塞的类似的 UDP 不可靠服务,该协议利用了 ECN。DCTCP(数据中心 TCP)是一种专门为数据中心网络设计的 TCP 版本,也利用了 ECN。


网站公告

今日签到

点亮在社区的每一天
去签到