TIME-WAIT状态是TCP四次挥手中的状态,在我的认知中,它是客户端socket的状态。但是最近遇到了个问题是:服务端上某个处于监听状态的socket有很多连接都处于这个状态。
当然在某些特定的场景下,服务端出现大量TIME-WAIT状态的socket状态是合理的,例如爬虫服务器,它要主动发起大量的连接去爬取其他网站上的数据,它们在这个场景中都属于客户端socket,爬完数据主动关闭连接了,所以会导致出现大量TIME-WAIT状态。但是我这个并非一个客户端socket,它是执行了listen的:
图中的9090端口是我监听的端口,只列出来了前10个TIME-WAIT状态的连接,和它一样的socket有接近16w个:
这让我百思不得其解,讲道理这不应该是客户端socket才会有的状态吗?为什么都已经是监听状态的socket还会出现这种状态?为了确认我的记忆没有错误,我又回顾了一次四次挥手的过程:
- 客户端发起关闭socket,此时发送一个FIN数据包到服务端。
- 服务端收到客户端的关闭请求后,回一个ACK表示确认收到了关闭请求。
- 服务端在一段时间后决定也关闭socket,于是发送一个FIN到客户端。
- 客户端收到服务端的关闭请求后,回复一个ACK表示收到了关闭请求。
几乎所有计算机网络相关书籍上对4次挥手的描述都是这样的,TIME-WAIT应该是出现在客户端socket一侧的。。为什么处于监听状态的socket会有呢?它不应该是LAST-ACK状态吗?
这个问题困扰了我大半天,实在是捉摸不透。也是晚上睡觉前突然想起才醒悟过来,发现这个问题原因。
实际上问题原因很简单,TIME-WAIT状态并非是客户端独有的状态,而是主动发起关闭连接方都会拥有的状态。即使是服务端、处于监听状态的socket,只要它向另一端发起了关闭请求,那么它就会产生这个状态。我们的服务端程序中,因为特定业务逻辑的关系,会经常性的主动断开连接,因此就导致了出现大量TIME-WAIT状态的socket。
为了验证这个观点,使用socket编写了两个小程序,一个作为服务端监听8080端口,一个作为客户端去连接服务端。当客户端连接上来后,服务端主动close掉,然后再观察连接确实处于TIME-WAIT状态。
总结:TIME-WAIT状态是客户端socket的状态这个观点实际上是一个思维误区,因为不管是从大学中、工作中聊到的四次挥手都是客户端主动断开连接的,导致我们的思维惯性就认为TIME-WAIT是属于客户端的状态!而实际上这个观点是错误的。
此处评论已关闭