网络专家TCP 接收窗口自动调节

Joseph Davies

欢迎来到 TechNet 杂志“网络专家”的第一部分。TechNet 网站上的专栏爱好者都知道我们探讨各种网络问题,我们每个月都将继续保持这个传统。如果您是新手,要查找以前专栏的存档,请访问网络专家站点

现在开始介绍我们的第一个主题 - TCP 接收窗口。

TCP 连接的吞吐量可以通过发送和接收应用程序、发送和接收 TCP 的实现以及 TCP 对等方之间的传输路径来限制。在本专栏中,我将介绍 TCP 接收窗口及其对 TCP 吞吐量的影响、TCP 窗口缩放的使用以及 Windows Vista™ 中的“接收窗口自动调节”新功能(可优化 TCP 接收数据吞吐量)。

TCP 接收窗口

TCP 连接具有许多重要的特点。首先,它们是两个应用层协议之间的逻辑点对点通信。TCP 不提供一对多的传递服务,它仅提供一对一的传递服务。

其次,TCP 连接是面向连接的。在数据可以传输之前,两个应用层过程必须通过 TCP 连接建立过程正式协商一个 TCP 连接。同样,TCP 连接在通过 TCP 连接终止过程协商之后正式关闭。

再次,在 TCP 连接中发送的可靠数据按顺序排列,且期望得到接收端的肯定确认。如果没有接收到肯定确认,则重传这个段。接收端一端会放弃重复的段,并按照正确顺序排列到达时失序的段。

最后,TCP 连接是全双工的。对于每个 TCP 对等方,TCP 连接都由两个逻辑管道组成:一个传出管道和一个传入管道。TCP 报头包含传出数据的序列号和传入数据的确认 (ACK)。

此外,TCP 将通过传入和传出逻辑管道发送的数据视为连续的字节流。每个 TCP 报头中的序列号和确认号都根据字节边界定义。TCP 并不会考虑字节流中的记录或消息边界。应用层协议必须正确地分析传入的字节流。

为了限制任一时刻可发送的数据量,并为接收端提供流量控制,TCP 对等方使用窗口实现这些目的。该窗口是接收端允许发送端发送的字节流的数据范围。发送端只能发送位于窗口内的字节流中的字节。该窗口随着发送端的出站字节流和接收端的入站字节流而滑动。

对于给定的逻辑管道(全双工 TCP 连接的一个方向),发送端维护一个发送窗口,接收端维护一个接收窗口。当传输中没有数据或 ACK 段时,逻辑管道的发送和接收窗口相互匹配。换句话说,发送端允许发送的出站字节流中的数据范围与接收端能够接收的入站字节流中的数据范围相匹配。图 1 说明了这种发送和接收关系。

图 1 匹配发送和接收窗口

图 1** 匹配发送和接收窗口 **(单击该图像获得较大视图)

为了表示接收窗口的大小,TCP 报头包含了一个 16 位的“窗口”字段。当接收端收到数据时,它把 ACK 发送回发送端以表明成功接收到这些字节。在每个 ACK 中,“窗口”字段表示接收窗口中剩余的字节数。当应用程序发送、确认和检索数据后,发送窗口和接收窗口都会滑动到右侧。接收窗口是用于控制可从发送端传送给接收端的未确认数据数量的窗口。

由于接收窗口中可能会有应用程序未检索到的数据以及已接收但尚未确认的数据,因此 TCP 接收窗口具有一些其他的结构,如图 2 所示。

图 2 TCP 接收窗口中的数据类型

图 2** TCP 接收窗口中的数据类型 **(单击该图像获得较大视图)

请注意最大接收窗口和当前接收窗口的区别。最大接收窗口的大小是固定的。当前接收窗口的大小是可变的,并对应于接收端允许发送端发送的剩余数据量。当前接收窗口大小是发送回发送端的 ACK 中通告的“窗口”字段值,等于最大接收窗口大小与已接收和确认但尚未被应用程序检索的数据量之间的差值。

TCP 接收窗口和 TCP 吞吐量

为了优化 TCP 吞吐量(假设为合理的无差错传输路径),发送端应该发送足够的数据包以填满发送端和接收端之间的逻辑管道。逻辑管道的容量可由以下公式计算:

Capacity in bits = path bandwidth in bits per second * round-trip time (RTT) in seconds

容量称为带宽延迟乘积 (BDP)。管道可以用粗(高带宽)和细(低带宽)或者长(高 RTT)和短(低 RTT)来表示。粗而长的管道的 BDP 最高。使用高 BDP 传输路径的示例包括卫星链接或带有洲际光缆链接的企业广域网 (WAN)。

增强高 BDP 传输的发送端性能

新的“接收窗口自动调节”功能增强了通过高 BDP 链接接收数据的性能,但是发送端的性能如何呢?

避免发送 TCP 对等方拥塞整个网络的现有算法被称为“慢启动”和“拥塞避免”。在连接最初发送数据和还原丢失段时,这些算法可以增大发送窗口,即发送端可以发送的段数量。

对于每个接收到的确认段(Windows XP 和 Windows Server 2003 中的 TCP)或每个已经确认的段(Windows Vista 和 Windows Server“Longhorn”中的 TCP),“慢启动”算法会以一个完整的 TCP 段增大发送窗口。对于每个已经确认的完整窗口的数据,“拥塞避免”算法以一个完整的 TCP 段增大发送窗口。

这些算法很好地适应较小的 BDP 和较小的接收窗口大小。然而,当面对一个具有较大接收窗口大小和较大 BDP 的连接时,例如在位于高速 WAN 链接(往返时间为 100 毫秒)上的两个服务器之间复制数据,利用这些算法增大发送窗口的速度就不足以充分利用连接带宽。

为了在上述情形下更好地利用 TCP 连接的带宽,下一代 TCP/IP 堆栈包括了复合 TCP (CTCP)。CTCP 可以更快地增大发送窗口,适用于拥有较大的接收窗口大小和 BDP 的连接。CTCP 试图通过监控延迟变化和损失来使这类连接的吞吐量最大化。此外,CTCP 确保其行为不会对其他 TCP 连接产生负面影响。

在 Microsoft 内部执行的测试中,对于 RTT 为 50 毫秒、传输速率为每秒 1 Gb 的连接,大型文件的备份时间几乎缩短了一半。对于具有更大 BDP 的连接,性能的改善更为明显。CTCP 和“接收窗口自动调节”配合使用,可以提高链接利用率,最终可以显著提高具有较大 BDP 的连接的性能。

默认情况下,运行 Windows Server“Longhorn”的计算机上启用 CTCP,而运行 Windows Vista 的计算机上则禁用 CTCP。可以使用“netsh interface tcp set global congestionprovider=ctcp”命令启用 CTCP,还可以使用“netsh interface tcp set global congestionprovider=none”命令禁用 CTCP。

TCP 报头中的“窗口”字段大小为 16 位,允许 TCP 对等方通告最大为 65,535 字节的接收窗口。您可以根据以下公式计算给定 TCP 窗口的近似吞吐量:

Throughput = TCP maximum receive windowsize / RTT

例如,对于 65,535 字节的接收窗口,在 RTT 为 100 毫秒的路径上只能达到速度大约为每秒 5.24 兆字节 (Mbps) 的吞吐量,而不管传输路径的实际带宽是多少。对于目前的高 BDP 传输路径,最初设计的 TCP 窗口大小即使达到最大值,仍然是吞吐量的瓶颈。

TCP 窗口缩放

为了提供可适应高速传输路径的更大窗口尺寸,RFC 1323 (ietf.org/rfc/rfc1323.txt) 定义了允许接收端通告大于 65,535 字节的窗口大小的窗口缩放。“TCP 窗口缩放”选项包括一个窗口缩放因子,该因子与 TCP 报头中的 16 位窗口字段结合时,可以将接收窗口大小最大增加到 1GB。“TCP 窗口缩放”选项只用于在连接建立过程的同步 (SYN) 段中发送数据。TCP 对等方都可以为接收窗口大小指定不同的窗口缩放因子。TCP 窗口缩放允许发送端通过一个连接发送更多的数据,可以使 TCP 节点更好地利用一些具有高 BDP 的传输路径类型。

尽管接收窗口大小对于 TCP 吞吐量而言非常重要,但确定最佳 TCP 吞吐量还有一个重要的因素,那就是应用程序检索接收窗口中累积数据的速度(应用程序检索速率)。如果应用程序不能检索数据,接收窗口就可以开始填充,导致接收端通告了更小的当前窗口大小。在极个别的情况下,整个最大接收窗口都会填满,导致接收端通告了 0 字节的窗口大小。在这种情况下,发送端必须停止发送数据,直到接收窗口已经清除为止。因此,要优化 TCP 吞吐量,必须将连接的 TCP 接收窗口设定为可同时反映该连接传输路径的 BDP 和应用程序检索速率的值。

即使您可以正确地确定 BDP 和应用程序检索速率,它们仍会随时间而变化。BDP 速率可以根据传输路径中的阻塞情况而变化,而应用程序检索速率会根据应用程序检索数据所在的连接数量而变化。

Windows XP 中的接收窗口

对于 Windows XP(和 Windows Server® 2003)中的 TCP/IP 堆栈,最大接收窗口的大小具有许多重要的属性。首先,默认值基于发送界面的链接速度。实际值自动调整为 TCP 连接建立过程中协商的最大段大小 (MSS) 的偶数增量。

其次,最大接收窗口的大小可以手动配置。可将注册表项 HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\TCPWindowSize 和 HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\Interface\InterfaceGUID\TCPWindowSize 的值设置为最大 65,535 字节(不带窗口缩放)或 1,073,741,823 字节(带窗口缩放)。

再次,最大接收窗口的大小可以使用窗口缩放。可通过将注册表项 HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\Tcp1323Opts 的值设置为 1 或 3 来启用窗口缩放。默认情况下,仅当接收的同步 (SYN) 段包含“窗口缩放”选项时,才在连接上使用窗口缩放。

最后,启动连接时,可使用应用程序的“SO_RCVBUF Windows Sockets”选项,指定连接的最大接收窗口大小。使用窗口缩放时,应用程序所指定的窗口大小必须大于 65,535 字节。

尽管 Windows XP 支持可缩放窗口,但其中的最大接收窗口大小仍然会限制吞吐量,因为它是针对所有 TCP 连接(除非由应用程序指定)的一个固定的最大大小,它可以增加某些连接的吞吐量,同时减少其他连接的吞吐量。另外,TCP 连接的最大接收窗口大小固定,不随应用程序检索速率的变化或传输路径中的阻塞而变化。

Windows Vista 中的接收窗口自动调节

为了优化 TCP 吞吐量,特别是具有高 BDP 的传输路径,Windows Vista(和代码名为“Longhorn”的 Windows Server 下一版本)中的下一代 TCP/IP 堆栈支持接收窗口自动调节功能。该功能通过测量 BDP 和应用程序检索速率,以及调整当前的传输路径和应用程序状况的窗口大小,来确定最合适的接收窗口大小。

默认情况下,“接收窗口自动调节”会启用 TCP 窗口缩放,它所允许的最大窗口大小为 16 MB。数据流通过连接时,下一代 TCP/IP 堆栈会监控连接,测量该连接当前的 BDP 和应用程序检索速率,并调整接收窗口大小以优化吞吐量。下一代 TCP/IP 堆栈不再使用 TCPWindowSize 注册表值。

“接收窗口自动调节”功能具有许多优点。它可以根据每个连接自动确定最佳的接收窗口大小。在 Windows XP 中,TCPWindowSize 注册表值适用于所有的连接。应用程序无需再通过“Windows Socket”选项指定 TCP 窗口大小。并且 IT 管理员也无需再为特定的计算机手动配置 TCP 接收窗口的大小。

使用“接收窗口自动调节”功能后,基于 Windows Vista 的 TCP 对等方通常会比基于 Windows XP 的 TCP 对等方通告更大的接收窗口大小。这使得其他 TCP 对等方可以通过发送更多的 TCP 数据段来将管道填入基于 Windows Vista 的 TCP 对等方,而无需等待 ACK(服从 TCP 拥塞控制)。对于如网页或电子邮件等典型的基于客户端的网络通信,Web 服务器或电子邮件服务器可以向客户端计算机更快更多地发送 TCP 数据,从而全面提高网络性能。连接的 BDP 和应用程序检索速率越高,性能的提高就越明显。

在数据传输中,将通常以较慢的速度发送的 TCP 数据包流快速发送,从而导致网络利用率出现更大的高峰,这就是该方法对网络造成的影响。基于 Windows XP 和 Windows Vista 的计算机在长而粗的管道上执行相同的数据传输时,传输的数据量相同。然而,基于 Windows Vista 的客户端计算机的数据传输更快,因为其具有更大的接收窗口大小,并且服务器能够填充从自身到客户端的管道。

由于“接收窗口自动调节”会增加高 BDP 传输路径的网络利用率,因此对于达到或接近最大容量的传输路径,限制使用服务质量 (QoS) 或应用程序发送速率可能会变得非常重要。为了满足此潜在的需要,Windows Vista 支持基于组策略的 QoS 设置,可以利用该设置为基于 IP 地址或 TCP 端口的信息流发送速率定义限制速率。有关详细信息,请参阅基于策略的 QoS 资源

增加高损失网络的 TCP 吞吐量

在高损失网络中,频繁的超时和重传可能会大大降低 TCP 吞吐量。高损失网络的一个例子就是无线网络,如基于 IEEE 802.11、通用分组无线业务 (GPRS) 或通用移动通信系统 (UMTS) 的网络,由于网络状况、信号衰减、电磁干扰和计算机的位置变化,可能会有较高的数据包丢失率。

下一代 TCP/IP 堆栈支持以下四种 RFC,可以优化高丢失率环境中的吞吐量:

RFC 2582:The NewReno Modification to TCP's Fast Recovery Algorithm(TCP 快速恢复算法 NewReno 修正)

RFC 2001 中定义的快速恢复算法基于 Reno 算法,由于快速重传事件而重传段时,Reno 算法可增加发送端能发送的数据量。Reno 算法适用于单个丢失的段,有多个丢失段时就不适用了。当数据窗口中的多个段丢失且发送端收到部分确认(仅对成功接收的那部分数据的确认)时,NewReno 算法通过更改快速恢复过程中发送端可以用来提高发送速率的方法,提供更大的吞吐量。

RFC 2883:An Extension to the Selective Acknowledgment (SACK) Option for TCP(TCP 选择确认 (SACK) 选项扩展)

RFC 2018 中定义的 SACK,允许接收端通过使用 SACK TCP 选项指示最多四个接收数据的非邻接块。RFC 2883 定义用于确认重复的数据包的 SACK TCP 选项中的字段的额外使用。发送端可以通过此操作确定何时重传了不必要的段并调整其行为,以防今后不必要的重传。发送的重传越少,整体吞吐量越合理。

RFC 3517:A Conservative Selective Acknowledgment-based Loss Recovery Algorithm for TCP(TCP 的基于保守选择确认的丢失恢复算法)

Windows Server 2003 和 Windows XP 中的 TCP/IP 当前实现只使用 SACK 信息确定未到达目标的 TCP 段。RFC 3517 定义了收到重复确认后使用 SACK 信息执行丢失恢复的方法,以便在连接上启用 SACK 时替代原来的快速恢复算法。下一代 TCP/IP 堆栈基于每个连接跟踪 SACK 信息并监控传入确认和重复确认,以便在目标未收到多个段时更快进行恢复。

RFC 4138:Forward RTO-Recovery (F-RTO):An Algorithm for Detecting Spurious Retransmission Timeouts with TCP and the Stream Control Transmission Protocol (SCTP)(使用 TCP 和流控制传输协议 (SCTP) 探测伪重传超时设定的算法)

RTT 突然增加时,可能会出现 TCP 段的伪重传现象,导致先前发送的段的重传超时设定 (RTO) 逐渐到期,TCP 开始重传它们。如果 RTT 增加正好发生在发送整个窗口的数据前,发送端可能会重传整个窗口的数据。F-RTO 算法通过以下行为防止 TCP 段的伪重传。

当多个段的 RTO 到期时,TCP 只重传第一个段。收到第一个确认后,TCP 开始发送新段(如果通告的窗口大小允许)。如果下一个确认确认超时但未重传的其他段,则 TCP 确定超时是伪超时,不重传超时的其他段。

这样的结果是,对于 RTT 突然和临时增加的环境(例如,当无线客户端从一个入口点漫游到另一个时),F-RTO 可防止不必要的段重传并更快地恢复到正常发送速率。基于 SACK 的丢失恢复和 F-RTO 最适用于使用 GPRS 链接的连接。

Joseph Davies是 Microsoft 的一位技术撰稿人,从 1992 年起一直在培训和编写 Windows 网络主题。他曾为 Microsoft Press 编写了五本著作,并且是每月的 TechNet 网络专家专栏的作者。

© 2008 Microsoft Corporation 与 CMP Media, LLC.保留所有权利;不得对全文或部分内容进行复制.