TCP连接终止前的TIME_WAIT状态

TIME_WAIT状态

客户端连接在接收到服务器结束报文段之后,并未直接进入CLOSED状态,而是转移到TIME_WAIT状态。
在这个状态,客户端连接要等待一段长为2 MSL(Maximum Segment Life,报文段最大生存时间)的时间,才能完全关闭。
MSL是TCP报文段在网络中最大生存时间,标准文档RFC 1122的建议值是2min(即2分钟)。

为何会有TIME_WAIT?

TIME_WAIT状态存在的原因有两点:
1、可靠地终止TCP连接。
2、保证让迟来的TCP报文段有足够的时间被识别并丢弃。

为何要这么做?
1的原因:
如果客户端给服务端发的最后一个ACK确认结束的报文丢失,那么服务器将重发结束报文段。
因此客户端需要停留在某个状态以处理重复收到的结束报文段。
不然客户端将回应服务器一个复位报文段(RST),服务器则会认为此是一个错误,因为它在等待客户端确认关闭连接的最后一个确认报文段(ACK)。

2的原因:
Linux系统上,一个TCP端口不能被同时打开多次。
当一个TCP连接处于TIME_WAIT状态时,将无法立即使用该连接占用着的端口来建立一个新连接。
如果没有TIME_WAIT状态,应用程序能够立即建立起一个和刚关闭的连接相似的连接。
这个新的、和原来相似的连接被称为原来连接的化身。新的化身可能接收到属于原来的连接的某些TCP报文段,显然不应该发生这种情况。

为啥是2MSL?
因为MSL是TCP报文段在网络中最大生存时间,所以2MSL的时间能保证网络上两个传输方向上尚未接收到的、迟到的TCP报文都已经丢失。
因此一个连接的新的化身可在2MSL之后安全地建立,而不会收到属于原来的连接的应用程序数据。

避免TIME_WAIT状态

避免目的:希望程序退出后能够立即重启。
由于客户端端口号的随机性,客户端一般和程序上次使用的端口号(TIME_WAIT状态)不同,所以客户端一般可以立即重启。

但是服务端总是使用同一个知名服务端口号,所以连接的TIME_WAIT状态将导致它不能立即重启。不过,我们可以通过socket选项
SO_REUSEADDR来强制进程立即使用处于TIME_WAIT状态的连接占用端口。

知识来源:《Linux高性能服务器编程》

你可能感兴趣的:(tcp,TIME-WAIT)