真实面经题目 · 原创解析

CLOSE_WAIT 和 TIME_WAIT 分别是什么?

CLOSE_WAIT 和 TIME_WAIT 都是 TCP 连接关闭过程中的状态,但含义完全不同。CLOSE_WAIT 出现在被动关闭方,表示对端已经发来 FIN,本端已经确认,但应用还没有调用 close 结束连接;TIME_WAIT 出现在主动关闭方,表示本端完成主动关闭后仍保留连接一段时间,用于处理延迟报文和保证对端收到最后的 ACK。

出现于:字节跳动 · 后端开发

60 秒回答模板

可以先按主动关闭和被动关闭来区分。CLOSE_WAIT 是被动关闭方收到对端 FIN 后进入的状态,内核已经回复 ACK,接下来要等本端应用关闭 socket 并发送自己的 FIN。如果大量 CLOSE_WAIT 长时间存在,通常说明应用层没有正确关闭连接、读写协程卡住、连接池泄漏或异常路径没有释放资源。TIME_WAIT 是主动关闭方发送最后 ACK 后进入的状态,需要等待 2MSL,目的是让网络中的旧报文自然过期,并在对端没有收到最后 ACK 时能够重传 ACK。大量 TIME_WAIT 不一定是 bug,高并发短连接服务很常见,但要结合端口耗尽、连接复用、keep-alive、连接池和内核参数判断。

考点 所属一侧
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

TCP 关闭的基本路径

TCP 是全双工协议,连接关闭不是简单的一次断开,而是两个方向分别关闭。主动关闭方先发送 FIN,表示自己不再发送数据;被动关闭方收到 FIN 后回复 ACK,此时被动方进入 CLOSE_WAIT,仍然可以继续发送剩余数据。随后被动方应用调用 close,发送自己的 FIN;主动关闭方收到后回复最后一个 ACK,并进入 TIME_WAIT。这个流程解释了为什么两个状态分别属于不同的一侧,也解释了它们的排查方向完全不同。

02

CLOSE_WAIT 的含义

CLOSE_WAIT 表示对端已经关闭发送方向,本端内核已经知道这件事并完成确认,但本端应用还没有真正关闭 socket。它本身不是内核延迟回收,而是在等待用户态程序做收尾动作。正常情况下,CLOSE_WAIT 应该很快过渡到 LAST_ACK;如果大量连接长期停在这里,重点要查应用代码是否在读到 EOF、异常返回、超时、半关闭通知或业务取消时没有执行 close。

03

TIME_WAIT 的含义

TIME_WAIT 表示主动关闭方已经完成四次挥手的最后 ACK,但连接不能立刻删除。原因有两个:第一,最后 ACK 可能丢失,被动关闭方会重发 FIN,主动关闭方需要还能识别并再次 ACK;第二,旧连接的延迟报文可能仍在网络中,等待 2MSL 能降低旧报文污染新连接的概率。它是 TCP 正确性的保护状态,不应一看到数量多就判定为异常。

04

如何判断是否异常

判断 CLOSE_WAIT 要看持续时间和是否持续增长。如果连接长时间不消失,几乎总是应用层释放问题。判断 TIME_WAIT 要结合流量形态:短连接、大量主动断开、没有连接复用时数量偏高很常见;真正有风险的是本机临时端口耗尽、连接建立失败、文件描述符压力、NAT 设备状态表压力或延迟异常。一个成熟回答要把状态机语义、业务连接模式和系统资源放在一起看。

05

治理思路

CLOSE_WAIT 的治理重心在代码路径:确保 finally 或 defer 关闭连接,连接池借还一致,读写超时可退出,异常分支释放资源,并通过 fd、堆栈、协程或线程栈定位卡住的位置。TIME_WAIT 的治理重心在连接模型:优先使用 keep-alive、HTTP/2、多路复用、连接池和服务端主动关闭策略,必要时再评估端口范围、TIME_WAIT 复用、负载均衡和内核参数。不能用调整内核参数掩盖应用层未关闭连接的问题。

易错点

  • 把 CLOSE_WAIT 当成正常等待超时回收,忽略它通常需要应用主动 close 才能离开。
  • 把 TIME_WAIT 一概视为故障,忽略它是主动关闭方为 TCP 正确性保留的协议状态。
  • 只靠修改内核参数处理 CLOSE_WAIT,实际没有修复 socket 泄漏根因。
  • 没有区分主动关闭方和被动关闭方,导致排查方向完全反了。

面试官追问

为什么 CLOSE_WAIT 多通常是应用问题?

因为内核已经收到对端 FIN 并回复 ACK,下一步要等本端应用关闭 socket。如果应用没有 close,内核无法替应用发送 FIN,连接就会停在 CLOSE_WAIT。

TIME_WAIT 为什么要等待 2MSL?

2MSL 能覆盖一个报文在网络中往返可能存活的最长时间,让旧连接的延迟报文自然失效,并允许主动关闭方在对端重发 FIN 时再次回复 ACK。

服务端 TIME_WAIT 很多一定说明服务端有问题吗?

不一定。谁主动关闭连接,谁更容易进入 TIME_WAIT。如果服务端主动断开短连接,服务端就会积累 TIME_WAIT。要看连接复用、主动关闭策略和资源是否真的受影响。

如何快速定位 CLOSE_WAIT 的来源?

先用连接统计确认本地端口、远端地址和进程,再看进程 fd 数、线程或协程栈、连接池状态和异常日志。重点找读到 EOF 或捕获异常后没有关闭连接的路径。