详解TCP连接的状态与关闭方式及Winserver系统下的TCP参数优化

详解TCP连接的状态与关闭方式及Winserver系统下的TCP参数优化




TCP连接的状态与关闭

1. TCP连接的状态

首先介绍一下TCP连接建立与关闭过程中的状态。TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用、特定数据包以及超时等,具体状态如下所示:

TCP连接的状态转换如下图所示

Converted Image

Converted Image

2. TCP连接的关闭方式

建 立TCP连接需要三次握手,而关闭连接则需要四次握手,并且分为主动关闭和被动关闭。这是由于TCP连接是全双工的,我关了你的连接,并不等于你关了我的 连接,因此双方都必须单独进行关闭。当一方完成它的数据发送任务后可以发送FIN包来终止这个方向的连接,表明自己不再有数据需要发送;收到FIN包的那 一方虽然不能再读取数据,但仍能发送数据。以Client主动关闭连接为例:

3. 对Server与Client的影响

由上面我们可以知道TIME_WAIT状态是一个比较难处理的问题,主动关闭连接的一方在发送最后一个ACK包后,无论对方是否收到都会进入TIME_WAIT状态,等待2MSL的时间,然后才能释放网络资源。

对 于Client而言,每个连接都需要占用一个端口,而系统允许的可用端口数不足65000个(这也是在TCP参数优化后才能达到)。因此,如果 Client发起过多的连接并主动关闭(假设没有重用端口或者连接多个Server),就会有大量的连接在关闭后处于TIME_WAIT状态,等待 2MSL的时间后才能释放网络资源(包括端口),于是Client会由于缺少可用端口而无法新建连接。

对Server 而言(特别是处理高并发短连接的Server),Server端与Client建立的连接是使用同一个端口的,即监听的端口,它要使用哈希表记录端口上的 每个连接,并受到文件描述符的最大打开数的限制。所以,如果Server主动关闭连接,同样会有大量的连接在关闭后处于TIME_WAIT状态,等待 2MSL的时间后才能释放网络资源

对于这种情况,有三种应对方式:

Windows系统下的TCP参数优化

通常会采用修改注册表的方式改进Windows的系统参数。所有的优化操作都通过修改注册表实现,需要使用regedit命令进入注册表并创建或修改参数,修改完成后需要重启系统,以使之生效。以下使用的参数值均为10进制。


1. TCPWindowSize

TCPWindowSize 的值表示TCP的窗口大小。TCP Receive Window(TCP数据接收缓冲)定义了发送端在没有获得接收端的确认信息的状态下可以发送的最大字节数。此数值越大,返回的确认信息就越少,相应的在 发送端和接收端之间的通信就越好。此数值较小时可以降低发送端在等待接收端返回确认信息时发生超时的可能性,但这将增加网络流量,降低有效吞吐率。TCP 在发送端和接收端之间动态调整一个最大段长度MSS(Maximum Segment Size)的整数倍。MSS在连接开始建立时确定,由于TCP Receive Window被调整为MSS的整数倍,在数据传输中完全长度的TCP数据段的比例增加,故而提高了网络吞吐率。

缺 省情况下,TCP将试图根据MSS来优化窗口大小,起始值为16KB,最大值为64KB。TCPWindowSize的最大值通常为65535字节 (64KB),以太网最大段长度为1460字节,低于64KB的1460的最大整数倍为62420字节,因而可以在注册表中将TCPWindowSize 设置为62420,作为高带宽网络中适用的性能优化值。具体操作如下:

浏 览至HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注 册表子键,在Parameters子键下创建或修改名为TCPWindowSize的REG_DWORD值,该值的范围是从0到65535,将该值设置为 62420。

2. TCP1323Opts

为 了更高效地利用高带宽网络,可以使用比上述TCP窗口大得多的TCP窗口大小,此特性是Windows 2000和Windows Server 2003中的新特性,称为TCP Window Scaling,它将以前的65535字节(64KB)的限制提高到了1073741824字节(1GB)。在带宽与延迟的乘积值很高的连接上(例如卫星 连接),可能需要将窗口的大小增加到64KB以上。使用TCP Window Scaling,系统可以允许确认信息间更大数据量的传输,增加了网络吞吐量及性能。发送端和接收端往返通信所需的时间被称为回环时间(RTT)。TCP Window Scaling仅在TCP连接的双方都开启时才真正有效。TCP有一个时间戳选项,通过更加频繁地计算来提高RTT值的估测值,此选项特别有助于估测更长 距离的广域网上连接的RTT值,并更加精确地调整TCP重发超时时间。时间戳在TCP报头提供了两个区域,一个记录开始重发的时间,另一个记录接收到的时 间。时间戳对于TCP Window Scaling,即确认信息收到前的大数据包传送特别有用,激活时间戳仅仅在每个数据包的头部增加12字节,对网络流量的影响微乎其微。数据完整性与数据 吞吐率最大化哪个更为重要是个需要评估的问题。在某些环境中,例如视频流传输,需要更大的TCP窗口,这是最重要的,而数据完整性排在第二位。在这种环境 中,TCP Window Scaling可以不打开时间戳。当发送端和接收端均激活TCP Window Scaling和时间戳时,此特性才有效。不过,若在发包时加入了时间戳,经过NAT之后,如果前面相同的端口被使用过,且时间戳大于这个连接发出的 SYN中的时间戳,就会导致服务器忽略该SYN,表现为用户无法正常完成TCP的3次握手。初始时生成小的TCP窗口,之后窗口大小将按照内部算法增大。 具体操作如下:

浏览至

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创建或修改名为TCP1323Opts的REG_DWORD值,

该值的具体含义为:

TCP1323Opts设置为激活TCP Window Scaling后,可以将上文中的注册表项TCPWindowSize的值增大,最大能达到1GB,为了达到最佳性能,这里的值最好设置成MSS的倍数,推荐值为256960字节。

3. TCP 控制块表

对 于每个TCP连接,控制变量保存在一个称为TCP控制块(TCB)的内存块中。TCB表的大小由注册表项MaxHashTableSize控制。在活动连 接很多的系统中,设定一个较大的表可以降低系统定位TCB表的时间。在TCB表上分区可以降低对表的访问的争夺。增加分区的数量,TCP的性能会得到优 化,特别是在多处理器的系统上。注册表项NumTcbTablePartitions控制分区的数量,默认是处理器个数的平方。TCB通常预置在内存中, 以防止TCP反复连接和断开时,TCB反复重新定位浪费时间,这种缓冲的方式促进了内存管理,但同时也限制了同一时刻允许的TCP连接数量。注册表项 MaxFreeTcbs决定了处于空闲等待状态的TCB重新可用之前的连接数量,在NT架构中常设置成高于默认值,以确保有足够的预置的TCB。从 Windows 2000开始添加了一个新特性,降低超出预置TCB运行的可能性。如果处于等待状态的连接多于MaxFreeTWTcbs中的设置,所有等待时间超过60 秒的连接将被强制关闭,以后再次启用。此特性合并到Windows 2000 Server和Windows Server 2003后,MaxFreeTcbs将不再用于优化性能。具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为MaxHashTableSize的REG_DWORD值,该值的范围是从1到65536,并且必须为2的N次方,缺省值为512,建议设为 8192。然后在Parameters子键下创建或修改名为NumTcbTablePartitions的REG_DWORD值,该值的范围是从1到 65536,并且必须为2的N次方,缺省值为处理器个数的平方,建议设为处理器核心数的4倍。

4. TcpTimedWaitDelay

TcpTimedWaitDelay 的值表示系统释放已关闭的TCP连接并复用其资源之前,必须等待的时间。这段时间间隔就是以前的Blog中提到的TIME_WAIT状态(2MSL,数据 包最长生命周期的两倍状态)。如果系统显示大量连接处于TIME_WAIT状态,则会导致并发量与吞吐量的严重下降,通过减小该项的值,系统可以更快地释 放已关闭的连接,从而为新连接提供更多的资源,特别是对于高并发短连接的Server具有积极的意义。

该项的缺省值是240,即等待4分钟后释放资源;系统支持的最小值为30,即等待时间为30秒。具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为TcpTimedWaitDelay的REG_DWORD值,该值的范围是从0到300,建议将该值设置为30。

5. MaxUserPort

MaxUserPort 的值表示当应用程序向系统请求可用的端口时,TCP/IP可分配的最大端口号。如果系统显示建立连接时出现异常,那么有可能是由于匿名(临时)端口数不够 导致的,特别是当系统打开大量端口来与Web service、数据库或其他远程资源建立连接时。

该 项的缺省值是十进制的5000,这也是系统允许的最小值。Windows默认为匿名(临时)端口保留的端口号范围是从1024到5000。为了获得更高的 并发量,建议将该值至少设为32768以上,甚至设为理论最大值65534,特别是对于模拟高并发测试环境的Client具有积极的意义。具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为MaxUserPort的REG_DWORD值,该值的范围是从5000到65534,缺省值为5000,建议将该值设置为65534。

6. 动态储备

动 态储备的值使系统能自动调整其配置,以接受大量突发的连接请求。如果同时接收到大量连接请求,超出了系统的处理能力,那么动态储备就会自动增大系统支持的 暂挂连接的数量(即Client已请求而Server尚未处理的等待连接数,TCP连接的总数包括已连接数与等待连接数),从而可减少连接失败的数量。系 统的处理能力和支持的暂挂连接的数量不足时,Client的连接请求将直接被拒绝。

缺省情况下,Windows 不启用动态储备,可以通过以下操作进行开启和设置:

浏览至HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters注册表子键,在Parameters子键下创建或修改下列名称的REG_DWORD值。

7. KeepAliveTime

KeepAliveTime 的值控制系统尝试验证空闲连接是否仍然完好的频率。如果该连接在一段时间内没有活动,那么系统会发送保持连接的信号,如果网络正常并且接收方是活动的,它 就会响应。如果需要对丢失接收方的情况敏感,也就是说需要更快地发现是否丢失了接收方,请考虑减小该值。而如果长期不活动的空闲连接的出现次数较多,但丢 失接收方的情况出现较少,那么可能需要增大该值以减少开销。

缺省情况下,如果空闲连接在7200000毫秒(2小时)内没有活动,系统就会发送保持连接的消息。 通常建议把该值设为1800000毫秒,从而丢失的连接会在30分钟内被检测到。具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为KeepAliveTime的REG_DWORD值,为该值设置适当的毫秒数。

8. KeepAliveInterval

KeepAliveInterval 的值表示未收到另一方对“保持连接”信号的响应时,系统重复发送“保持连接”信号的频率。在无任何响应的情况下,连续发送“保持连接”信号的次数超过 TcpMaxDataRetransmissions(下文将介绍)的值时,将放弃该连接。如果网络环境较差,允许较长的响应时间,则考虑增大该值以减少 开销;如果需要尽快验证是否已丢失接收方,则考虑减小该值或TcpMaxDataRetransmissions值。

缺省情况下,在未收到响应而重新发送“保持连接”的信号之前,系统会等待1000毫秒(1秒),可以根据具体需求修改,具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为KeepAliveInterval的REG_DWORD值,为该值设置适当的毫秒数。

9. TcpMaxDataRetransmissions

TcpMaxDataRetransmissions 的值表示TCP数据重发,系统在现有连接上对无应答的数据段进行重发的次数。如果网络环境很差,可能需要提高该值以保持有效的通信,确保接收方收到数据; 如果网络环境很好,或者通常是由于丢失接收方而导致数据的丢失,那么可以减小该值以减少验证接收方是否丢失所花费的时间和开销。

缺省情况下,系统会重新发送未返回应答的数据段5次,可以根据具体需求修改,具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为TcpMaxDataRetransmissions的REG_DWORD值,该值的范围是从0到4294967295,缺省值为5,根据实 际情况进行设置。

10. TcpMaxConnectRetransmisstions

TcpMaxConnectRetransmisstions 的值表示TCP连接重发,TCP退出前重发非确认连接请求(SYN)的次数。对于每次尝试,重发超时是成功重发的两倍。在Windows Server 2003中默认超时次数是2,默认超时时间为3秒(在注册表项TCPInitialRTT中)。速度较慢的WAN连接中超时时间可相应增加,不同环境中可 能会有不同的最优化设置,需要在实际环境中测试确定。超时时间不要设置太大否则将不会发生网络连接超时时间。具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表子键,在Parameters子键下创 建或修改名为TcpMaxConnectRetransmisstions的REG_DWORD值,该值的范围是从0到255,缺省值为2,根据实际情况 进行设置。然后在Parameters子键下创建或修改名为TCPInitialRTT的REG_DWORD值,同样根据实际情况进行设置。

11. TcpAckFrequency

TcpAckFrequency 的值表示系统发送应答消息的频率。如果值为2,那么系统将在接收到2个分段之后发送应答,或是在接收到1个分段但在200毫秒内没有接收到任何其他分段的 情况下发送应答;如果值为3,那么系统将在接收到3个分段之后发送应答,或是在接收到1个或2个分段但在200毫秒内没有接收到任何其他分段的情况下发送 应答,以此类推。如果要通过消除应答延迟来缩短响应时间,那么建议将该值设为1。在此情况下,系统会立即发送对每个分段的应答;如果连接主要用于传输大量 数据,而200毫秒的延迟并不重要,那么可以减小该值以降低应答的开销。

缺省情况下,系统将该值设为2,即每隔一个分段应答一次。该值的有效范围是0到255,其中0表示使用缺省值2,可以根据具体需求修改,具体操作:

浏览至

HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\TCPIP\Parameters\Interfaces\\xx(xx由网络 适配器决定)注册表子键,在xx子键下创建或修改名为TcpAckFrequency的REG_DWORD值,该值的范围是从1到13,缺省值为2,根据 希望每发送几个分段返回一个应答而设置该值,建议百兆网络设为5,千兆网络设为13。


另外几篇文章:


如何修改windows服务器最大的tcp连接数
 
在做性能测试测试时候,如果被测试的系统页面很简单,并且性能很好,这样会导致压力机得tcp链接数不够而导致如下错误:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Parameters\TcpTimedWaitDelay to 30
and HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\tcpip\Parameters\MaxUserPort to 65534
and rebooting the machine
See the readme.doc file for more information

通过百度搜索介绍最多的还是让修改TimedWaitDelay 和MaxUserPort这2个值,其中是将TimedWaitDelay修改的相对小点,可以根据实际情况来定,

同时将MaxUserPort这个值修改大些,但是修改完并重启机器后,该问题仍然存在,通过多方查资料,然后对一些注册表进行修改:

[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
TcpNumConnections = 0x00fffffe (Default = 16,777,214)
以上注册表信息配置单机的最大允许的TCP连接数,默认为 16M。这个数值看似很大,这个并不是限制最大连接数的唯一条件,还有其他条件会限制到TCP 连接的最大连接数。
最大动态端口数
TCP客户端和服务器连接时,客户端必须分配一个动态端口,默认情况下这个动态端口的分配范围为 1024-5000 ,也就是说默认情况下,客户端最多可以同时发起3977 个Socket 连接。我们可以修改如下注册表来调整这个动态端口的范围
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxUserPort = 5000 (Default = 5000, Max = 65534)

最大TCB 数量

系 统为每个TCP 连接分配一个TCP 控制块(TCP control block or TCB),这个控制块用于缓存TCP连接的一些参数,每个TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就说,每个TCP连接会占用 1KB 的系统内存。

系统的最大TCB数量由如下注册表设置决定
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)
非Server版本,MaxFreeTcbs 的默认值为1000 (64M 以上物理内存)

Server 版本,这个的默认值为 2000。

也就是说,默认情况下,Server 版本最多同时可以建立并保持2000个TCP 连接。
最大TCB Hash table 数量

TCB 是通过Hash table 来管理的,下面注册表设置决定了这个Hash table 的大小

HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters]
MaxHashTableSize = 512 (Default = 512, Range = 64-65536)

这个值指明分配 pagepool 内存的数量,也就是说,如果MaxFreeTcbs = 1000 , 则 pagepool 的内存数量为 500KB

那么 MaxHashTableSize 应大于 500 才行。这个数量越大,则Hash table 的冗余度就越高,每次分配和查找 TCP 连接用时就越少。这个值必须是2的幂,且最大为65536.

MaxUserPort = 65534 (Decimal)
MaxHashTableSize = 65536 (Decimal)
MaxFreeTcbs = 16000 (Decimal)

这里我们可以看到 MaxHashTableSize 被配置为比MaxFreeTcbs 大4倍,这样可以大大增加TCP建立的速度。



关于提高UDP发送效率的方法
UDP的发送效率和什么因素有关呢?

直观觉得,UDP的切包长越大,应该发送效率越高(最长为65536)。可是依据实际測试和在网上查到的资料的结果,包长度为1024为发送效率最高。



这样的结果让人感到疑惑,为什么是1024这样的奇怪的值呢?为什么不是MTU(最小发送单元)的长度(即1500-28)呢?

后来调查发现,Windows的网络底层,默认UDP分片长度为1024时,走的是高速通道模式,详细如何的高速通道?没有再继续深入研究。

通过改动以下的注冊表能够加大1024.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters\FastSendDatagramThreshold

而且须要改动网卡注冊表的MTU与上面的值一致,详细注冊表项例如以下所看到的:

HKEY_LOCAL_MACHINE\\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\MTU

注:实测修改
FastSendDatagramThreshold和MTU反而会减慢网速,可根据情况而定。


在Windows的注册表设置中,TcpAckFrequency和TcpDelAckTicks是两个关于TCP确认(ACK)包发送策略的参数。这两个参数控制的是延迟确认(Delayed ACK)的行为,但它们的作用略有不同。

TcpAckFrequency

路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces{Interface_GUID}

用途:这个参数用于控制每接收到多少个包发送一个确认(ACK)。默认情况下,该值通常不设置,TCP栈会每接收两个包发送一个ACK。

修改方式:如果将TcpAckFrequency设置为1,则每收到一个TCP数据包就立即发送一个ACK,这相当于禁用了延迟确认机制。

TcpDelAckTicks

路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces{Interface_GUID}{Interface_GUID}

用途:这个参数控制的是接收到数据包后,延迟多长时间发送确认(ACK)。默认情况下,Windows可能会等待一个固定的间隔(大约为200毫秒),以期望在此期间内收到更多的数据包,从而可以一次确认多个数据包。

修改方式:如果将TcpDelAckTicks设置为0,那么接收到数据包后将不会有任何延迟,立即发送确认(ACK)。这与将TcpAckFrequency设置为1有类似的效果,但更直接地针对延迟的调整。

两者的关系

在大多数情况下,修改这两个参数中的任何一个都会影响TCP的延迟确认行为。不过,TcpDelAckTicks更多地影响延迟的时间长度,而TcpAckFrequency直接控制基于接收到的数据包数量的确认发送频率。

对于绝大多数应用和环境,使用默认的TCP设置就足够好,因为TCP协议已经设计得很好地平衡了性能和网络效率。不过,在特定的高性能环境或低延迟要求的场景中(例如游戏服务器、高频交易平台),这些参数的调整可能会有所帮助。

注意事项

修改这些TCP设置可能会对网络性能产生不可预见的影响,因此在进行任何永久性调整前,建议在控制好的环境中进行充分的测试。

修改注册表涉及到系统级的配置更改,应谨慎操作,确保有相关的备份和恢复方案。



windows上关闭Nagle算法

下 面的设置可以调整或禁用 nagel 算法。禁用 nagel 算法以后, 允许很小的包没有延迟立即发送。建议对某些游戏关闭 nagel 算法, 这样做对文件传输/吞吐量有负面影响。默认状态( 开启nagel )为了提高性能, 会把几个小数据包合并一起, 为了有效传输更大的数据包。虽然这提高了整体性能,并降低了TCP/ IP开销, 但可能会短暂延迟较小的数据包的传输。切记禁用 Nagle 算法可能对文件传输有一些负面影响, 只能帮助某些游戏减少延迟.

为了实现这个调整,在注册表编辑器(开始>运行> REGEDIT)找到:
此设置配置最大数量的ACKs ( Windows XP/2003/Vista/2008 )
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{NIC-id}
将有多个网卡接口有列出,例如: {1660430C-B14A-4AC2-8F83-B653E83E8297}. 找到与你 IP 地址相同的地址, 创建一个新的 DWORD 值:
TcpAckFrequency=1
解释:(DWORD value, 1=disable, 2=default, 2-n=send ACKs if outstanding ACKs before timed interval. Setting not present by default).

对 于游戏性能,推荐的是1(禁用)。对于纯吞吐量和数据流,您可以尝试值超过2。如果您尝试较大的值,只要确保 TcpAckFrequency* MTU 小于 RWIN 就行, since the sender may stop sending data if RWIN fills witout acknowledgement.

此外,找到下面的键(win7 下需要 开始→控制面板→程序→程序和功能→打开或关闭windows功能, 开启 Microsoft Message Queue 才能看见 Parameters):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSMQ\Parameters
添加一个新的DWORD值:
TCPNODELAY=1
解释:(DWORD值为0启用Nagle算法,1禁用,默认情况下不存在)

要配置的ACK间隔超时(只有启用 Nagel 的时候才有效),找到(新增)以下注册表项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{NIC-id}

TcpDelAckTicks=0
解释:(DWORD value, default=2, 0=disable nagling, 1-6=100-600 ms).
你可以设置为 1 来将 NAGLE 的延迟时间从默认的 200ms 缩减到100ms.