不要被惯性扼杀了思维:为什么监听状态的SOCKET会产生TIME-WAIT状态?

马谦马谦马谦 2020年4月4日23:58:53 发表评论
文章最后编辑于:2020-4-5 00:15:06

TIME-WAIT状态是TCP四次挥手中的状态,在我的认知中,它是客户端socket的状态。但是最近遇到了个问题是:服务端上某个处于监听状态的socket有很多连接都处于这个状态。

当然在某些特定的场景下,服务端出现大量TIME-WAIT状态的socket状态是合理的,例如爬虫服务器,它要主动发起大量的连接去爬取其他网站上的数据,它们在这个场景中都属于客户端socket,爬完数据主动关闭连接了,所以会导致出现大量TIME-WAIT状态。但是我这个并非一个客户端socket,它是执行了listen的:

不要被惯性扼杀了思维:为什么监听状态的SOCKET会产生TIME-WAIT状态?

图中的9090端口是我监听的端口,只列出来了前10个TIME-WAIT状态的连接,和它一样的socket有接近16w个:

不要被惯性扼杀了思维:为什么监听状态的SOCKET会产生TIME-WAIT状态?

这让我百思不得其解,讲道理这不应该是客户端socket才会有的状态吗?为什么都已经是监听状态的socket还会出现这种状态?为了确认我的记忆没有错误,我又回顾了一次四次挥手的过程:

不要被惯性扼杀了思维:为什么监听状态的SOCKET会产生TIME-WAIT状态?

  1. 客户端发起关闭socket,此时发送一个FIN数据包到服务端。
  2. 服务端收到客户端的关闭请求后,回一个ACK表示确认收到了关闭请求。
  3. 服务端在一段时间后决定也关闭socket,于是发送一个FIN到客户端。
  4. 客户端收到服务端的关闭请求后,回复一个ACK表示收到了关闭请求。

几乎所有计算机网络相关书籍上对4次挥手的描述都是这样的,TIME-WAIT应该是出现在客户端socket一侧的。。为什么处于监听状态的socket会有呢?它不应该是LAST-ACK状态吗?

这个问题困扰了我大半天,实在是捉摸不透。也是晚上睡觉前突然想起才醒悟过来,发现这个问题原因。

实际上问题原因很简单,TIME-WAIT状态并非是客户端独有的状态,而是主动发起关闭连接方都会拥有的状态。即使是服务端、处于监听状态的socket,只要它向另一端发起了关闭请求,那么它就会产生这个状态。我们的服务端程序中,因为特定业务逻辑的关系,会经常性的主动断开连接,因此就导致了出现大量TIME-WAIT状态的socket。

为了验证这个观点,使用socket编写了两个小程序,一个作为服务端监听8080端口,一个作为客户端去连接服务端。当客户端连接上来后,服务端主动close掉,然后再观察连接确实处于TIME-WAIT状态。

总结:TIME-WAIT状态是客户端socket的状态这个观点实际上是一个思维误区,因为不管是从大学中、工作中聊到的四次挥手都是客户端主动断开连接的,导致我们的思维惯性就认为TIME-WAIT是属于客户端的状态!而实际上这个观点是错误的。

本文共执行63次查询,耗时0.463秒!
马谦马谦马谦

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: