【转】Socket中的TIME_WAIT状态

本文深入探讨了TCP连接断开时的TIME_WAIT状态,解释了该状态存在的必要性及如何通过设置减少其影响。

 Socket中的TIME_WAIT状态


在高并发短连接的server端,当server处理完client的请求后立刻closesocket此时会出现time_wait状态然后如果client再并发2000个连接,此时部分连接就连接不上了,用linger强制关闭可以解决此问题,但是linger会导致数据丢失,linger值为0时是强制关闭,无论并发多少多能正常连接上,如果非0会发生部分连接不上的情况!(可调用setsockopt设置套接字的linger延时标志,同时将延时时间设置为0。)
TCP/IP的RFC文档。TIME_WAIT是TCP连接断开时必定会出现的状态。
是无法避免掉的,这是TCP协议实现的一部分。
在WINDOWS下,可以修改注册表让这个时间变短一些
time_wait的时间为2msl,默认为4min.
你可以通过改变这个变量:
TcpTimedWaitDelay
把它缩短到30s


TCP要保证在所有可能的情况下使得所有的数据都能够被投递。当你关闭一个socket时,主动关闭一端的socket将进入TIME_WAIT状态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。当一个socket关闭的时候,是通过两端互发信息的四次握手过程完成的,当一端调用close()时,就说明本端没有数据再要发送了。这好似看来在握手完成以后,socket就都应该处于关闭CLOSED状态了。但这有两个问题,首先,我们没有任何机制保证最后的一个ACK能够正常传输,第二,网络上仍然有可能有残余的数据包(wandering duplicates),我们也必须能够正常处理。
通过正确的状态机,我们知道双方的关闭过程如下




假设最后一个ACK丢失了,服务器会重发它发送的最后一个FIN,所以客户端必须维持一个状态信息,以便能够重发ACK;如果不维持这种状态,客户端在接收到FIN后将会响应一个RST,服务器端接收到RST后会认为这是一个错误。如果TCP协议能够正常完成必要的操作而终止双方的数据流传输,就必须完全正确的传输四次握手的四个节,不能有任何的丢失。这就是为什么socket在关闭后,仍然处于 TIME_WAIT状态,因为他要等待以便重发ACK。
如果目前连接的通信双方都已经调用了close(),假定双方都到达CLOSED状态,而没有TIME_WAIT状态时,就会出现如下的情况。现在有一个新的连接被建立起来,使用的IP地址与端口与先前的完全相同,后建立的连接又称作是原先连接的一个化身。还假定原先的连接中有数据报残存于网络之中,这样新的连接收到的数据报中有可能是先前连接的数据报。为了防止这一点,TCP不允许从处于TIME_WAIT状态的socket建立一个连接。处于TIME_WAIT状态的socket在等待两倍的MSL时间以后(之所以是两倍的MSL,是由于MSL是一个数据报在网络中单向发出到认定丢失的时间,一个数据报有可能在发送图中或是其响应过程中成为残余数据报,确认一个数据报及其响应的丢弃的需要两倍的MSL),将会转变为CLOSED状态。这就意味着,一个成功建立的连接,必然使得先前网络中残余的数据报都丢失了。
由于TIME_WAIT状态所带来的相关问题,我们可以通过设置SO_LINGER标志来避免socket进入TIME_WAIT状态,这可以通过发送RST而取代正常的TCP四次握手的终止方式。但这并不是一个很好的主意,TIME_WAIT对于我们来说往往是有利的。



TCPTIME_WAIT 状态是连接关闭过程中的关键环节,对网络稳定性和资源管理至关重要。 ### 本质与产生原因 当连接主动关闭方(先发送 FIN 的一端)收到对端的 FIN + ACK 后,进入 TIME_WAIT 状态状态持续时间为 2 × MSL(Maximum Segment Lifetime,报文最大生存时间)。RFC 793 [Postel 1981c] 指出 MSL 为 2 分钟,不过实现中的常用值是 30 秒、1 分钟或 2 分钟 [^1][^2]。 ### 核心作用 虽然引用中未明确提及核心作用,但从 TCP 机制原理来说,TIME_WAIT 状态有两个重要作用。一是确保最后一个 ACK 报文能到达对端,防止对端因未收到 ACK 而重发 FIN 报文。若没有 TIME_WAIT 状态,主动关闭方关闭连接后,对端重发的 FIN 报文会让主动关闭方回复 RST 报文,使对端产生错误。二是避免新旧连接混淆,在 2MSL 时间内,旧连接的所有报文都会消失,新连接不会受到旧连接延迟报文的影响。 ### 发生场景 主动发起关闭连接的一方会进入 TIME_WAIT 状态,需要注意的是,并非只有客户端才能主动关闭连接,服务器也可能主动断开很多 TCP 连接,从而出现大量的 TIME_WAIT 状态TCP 连接 [^3]。 ### TCP状态中的位置 在 TCP 状态机中,各状态如下:CLOSED 表示无连接是活动的或正在进行;LISTEN 是服务器在等待进入呼叫;SYN_RECV 意味着一个连接请求已经到达,等待确认;SYN_SENT 表示应用已经开始打开一个连接;ESTABLISHED 是正常数据传输状态;FIN_WAIT1 表示应用说它已经完成;FIN_WAIT2 表示另一边已同意释放;ITMED_WAIT 表示等待所有分组死掉;CLOSING 表示两边同时尝试关闭;TIME_WAIT 表示另一边已初始化一个释放;LAST_ACK 表示等待最后一个 ACK 信号就关闭 [^4]。 ### 代码示例(Python 简单模拟 TCP 连接关闭) ```python import socket # 创建一个 TCP 套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 8888)) server_socket.listen(1) print('等待客户端连接...') conn, addr = server_socket.accept() print(f'连接来自: {addr}') # 模拟数据传输 data = conn.recv(1024) print(f'收到数据: {data.decode()}') # 模拟主动关闭连接 conn.sendall(b'Goodbye!') conn.close() # 这里可能会进入 TIME_WAIT 状态(如果是主动关闭方) server_socket.close() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值