真实面经题目 · 原创解析

TCP 为什么需要四次挥手?

TCP 需要四次挥手,是因为 TCP 是全双工协议,两个方向的数据流要分别关闭。主动关闭方发送 FIN 只表示自己不再发送数据,对方收到后先 ACK 确认,但对方可能还有未发送完的数据,等它也发送完后再发 FIN,主动关闭方再 ACK,因此通常是四个报文段。

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

60 秒回答模板

可以从全双工和半关闭解释。TCP 连接包含两个独立方向:A 到 B 和 B 到 A。A 主动关闭时发送 FIN,表示 A 到 B 方向没有数据了;B 收到后必须 ACK,但此时 B 到 A 方向可能还要继续发送剩余数据,所以不能立刻关闭整个连接。等 B 的应用层也决定关闭,B 再发送 FIN,表示 B 到 A 方向也结束;A 收到后回复 ACK,并进入 TIME_WAIT 等待一段时间,确保最后 ACK 能被重传并让旧报文在网络中消失。若 B 的 ACK 和 FIN 恰好合并,报文数量可能看起来少于四个,但逻辑上仍是两个方向分别关闭。

考点 两个方向
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

全双工本质

TCP 连接建立后,双方都可以同时发送和接收数据。关闭连接不是拔掉一根单向线,而是要分别关闭两个方向的数据流。一个方向不再发送,并不意味着另一个方向也已经没有数据。四次挥手反映的正是全双工连接在关闭阶段的独立性。

02

第一次 FIN

主动关闭方发送 FIN,含义是我这边已经没有数据要发了。发送 FIN 后,主动关闭方进入 FIN_WAIT_1,仍然可以接收对方数据。FIN 会消耗一个序号,接收方必须确认。这个阶段只关闭主动方到被动方的发送方向,不关闭反向数据流。

03

第二次 ACK

被动关闭方收到 FIN 后,内核会回复 ACK,告诉对方 FIN 已收到。此时被动方通常进入 CLOSE_WAIT,等待本地应用调用 close。CLOSE_WAIT 存在的原因是应用可能还有数据要写回,或者还没完成业务收尾。只要应用不关闭,内核不能擅自替它发送 FIN。

04

第三和第四次

当被动方应用也完成发送并关闭连接时,内核发送 FIN,表示反向数据流也结束。主动关闭方收到后回复 ACK,随后进入 TIME_WAIT。被动方收到这个 ACK 后可以进入 CLOSED。到这里,两个方向都确认没有新数据,连接资源才能完整释放。

05

TIME_WAIT 价值

主动关闭方最后进入 TIME_WAIT 不是多余等待。它有两个作用:一是如果最后 ACK 丢失,被动方会重发 FIN,主动方还能再次 ACK;二是让网络中属于旧连接的延迟报文自然过期,避免同一四元组快速复用后被旧报文干扰。等待时长通常与最大报文生存时间相关。

易错点

  • 把四次挥手解释成 TCP 不可靠所以多确认一次,忽略全双工两个方向独立关闭。
  • 认为收到 FIN 后对方必须立刻关闭,无法解释 CLOSE_WAIT 和剩余数据发送。
  • 把 TIME_WAIT 当成无意义状态,忽略最后 ACK 重传和旧报文过期的作用。
  • 绝对化地说挥手一定有四个报文,忽略 ACK 与 FIN 在特殊情况下可能合并。

面试官追问

为什么建立连接是三次握手,关闭却常见四次挥手?

建立时双方的 SYN 和 ACK 可以自然合并,服务端确认客户端 SYN 的同时发送自己的 SYN。关闭时被动方收到 FIN 后可能还有数据要发,ACK 和自己的 FIN 往往不能立即合并。

四次挥手一定是四个包吗?

不一定。如果被动方没有剩余数据且内核时机合适,ACK 和 FIN 可能合并发送。但逻辑上仍然是两个方向分别确认关闭。

大量 CLOSE_WAIT 说明什么?

说明对端已经关闭发送方向,本机也确认了,但本机应用迟迟没有关闭 socket。常见原因是代码没有正确 close、线程阻塞或连接生命周期管理有缺陷。

TIME_WAIT 过多怎么处理?

先判断是否是正常短连接高峰,再考虑连接复用、长连接、调整应用主动关闭方、扩大端口范围和合理内核参数。不能为了减少数量盲目破坏协议安全性。