TCP 三次握手与四次挥手如何进行,为什么要四次挥手?
未标记
考查重点:连接建立与双向半关闭。SYN/SYN-ACK/ACK 建连,双方各发 FIN/ACK 关闭发送方向;一方关闭不代表另一方无数据,报文可合并
本题目录
参考答案
核心回答
TCP 三次握手通过 SYN、SYN+ACK、ACK 交换并确认双方的初始序列号,建立连接。关闭时则要分别关闭两个发送方向:一方不再发送,不代表另一方也立刻没有数据,所以通常表现为 FIN、ACK、FIN、ACK 四个报文段。
“四次挥手”不是固定的抓包数量。确认对端 FIN 的 ACK,可以与本端的 FIN 合并;同时关闭、重传或 RST 中止连接,也会产生不同的报文和状态路径。
三次握手如何进行
以 A 主动连接、B 已经监听为例,先忽略报文携带应用数据的情况:
- A 发
SYN。 携带自己的初始序列号 x,进入SYN_SENT。 - B 发
SYN+ACK。 用确认号 x+1 确认 A 的SYN,同时携带自己的初始序列号 y,进入SYN_RCVD。 - A 发
ACK。 用确认号 y+1 确认 B 的SYN。A 此时进入ESTABLISHED;B 收到有效确认后,也进入ESTABLISHED。
SYN 占用一个序列号,所以确认号加一;普通纯 ACK 本身不占用序列号。第三次 ACK 也可以携带数据。
三次的关键是双方都要发送自己的序列号,并获得对方确认。B 在第二次报文中把自己的 SYN 与对 A 的确认合并,所以通常三次就够;如果只有两次,B 还不能确认 A 是否收到了自己的 SYN。
这也用于避免历史重复 SYN 引起错误建连:B 不能只凭收到一个 SYN,就认定对方正在参与这次连接;还需要对方对本次序列号作出有效确认。握手完成只是建立了传输连接,后续可靠传输仍依赖确认、重传、流量控制等机制。
四次挥手如何进行
以 A 先关闭发送方向、B 随后关闭为例:
- A 发
FIN,进入FIN_WAIT_1。 表示 A 的发送数据到此结束。FIN排在此前的数据之后,也占用一个序列号。 - B 确认
FIN,进入CLOSE_WAIT。 A 收到确认后进入FIN_WAIT_2。此时 A 到 B 的方向已结束,但 B 仍可向 A 发送剩余数据,这就是半关闭。 - B 也发
FIN,进入LAST_ACK。 本端应用准备结束发送后,B 关闭自己的发送方向,等待确认。 - A 确认 B 的
FIN,进入TIME_WAIT。 B 收到确认后进入CLOSED;A 完成TIME_WAIT等待后,再释放相应连接状态。
若 A 的 FIN 序列号是 u,B 应确认 u+1;B 的 FIN 序列号是 v,A 应确认 v+1。u 和 v 是各自在关闭时的序号,与此前实际传输了多少数据有关。
收到 FIN 的含义是“对方不再发送”,并不要求本端马上停止发送。例如 A 已提交完请求并关闭发送方向,B 仍可能需要把结果发完。Linux 的 shutdown 可以单独关闭发送方向,也体现了这种半关闭能力;它与直接把双向通信一起结束的语义不同。
为什么不能总是把挥手合成三次
B 收到 FIN 后,需要确认 A 的结束位置,但 B 什么时候停止发送由本端应用和发送数据决定,这两个时机未必一致。因此常见流程是先 ACK,之后再 FIN。
如果 B 已经准备结束发送,而且确认 A 的 ACK 尚未单独发出,就可能把“确认 A”和“本端也结束”放进同一个 FIN+ACK 报文段,形成三次挥手。延迟确认机制可以提供合并机会,但是否合并仍受具体 TCP 实现和应用关闭时机影响,不能说没有待发送数据就一定只有三次。
TIME_WAIT 在等什么
在上述正常关闭流程中,A 的 FIN 已得到确认,随后 A 收到 B 的 FIN 并回复最终 ACK,才进入 TIME_WAIT。它有两个主要作用:
- 给最终
ACK丢失留下补救机会。 如果 B 没收到确认,会重传FIN;A 保留连接状态,就能再次确认,而不是把对方的重传当作不存在连接的报文。收到相应重复FIN时,还会重新开始等待计时。 - 降低旧报文干扰新连接的风险。 在重新使用同一连接四元组前留出时间,让旧连接的延迟报文消失,避免它们被误认为新连接的数据。
协议用 2MSL 描述这个等待窗口,MSL 是报文段的最大生存时间,不是 RTT。实际系统的计时与复用规则有实现差异,不能给所有系统套一个固定秒数。
TIME_WAIT 不固定属于客户端或服务端,取决于关闭路径。上述例子中是 A;同时关闭时,双方都可能经过 CLOSING 后进入 TIME_WAIT。RST 中止则是另一条路径,不能理解为“谁调用关闭,谁在任何情况下都会等 2MSL”。
常见追问
第三次握手的 ACK 丢了怎么办?
B 未收到有效确认时会重传 SYN+ACK,A 可以再次确认;A 后续携带有效 ACK 的数据报文也可能完成这个确认过程。普通纯 ACK 不靠自己的重传计时器不断重发,恢复依赖对方重传或后续报文,具体超时受实现影响。
CLOSE_WAIT 和 TIME_WAIT 有什么区别?
CLOSE_WAIT 表示已经收到对方 FIN,本端应用尚未完成发送方向的关闭;持续大量堆积时,应检查连接释放、异常分支或处理线程是否卡住。TIME_WAIT 则是正常关闭中的保护等待,不能仅凭数量多就认定泄漏,仍要结合连接频率、端口和资源压力判断。
参考资料
- 国内:JavaGuide:TCP 三次握手和四次挥手:借鉴握手序号、关闭状态与 FIN/ACK 合并的说明,组织正文中的正常建连、双向独立关闭及四次挥手的报文合并条件。
- 国内:JavaGuide:TCP TIME_WAIT:最终 ACK 丢失、旧报文风险和 CLOSE_WAIT 对比部分,解释等待状态的用途及排查时应区分的含义。
- 国内:小林 coding:TCP 四次挥手,可以变成三次吗:参考延迟确认与应用关闭时机的讨论,解释正文中 ACK 与 FIN 获得合并机会的条件。
- 国外:IETF:RFC 9293 — Transmission Control Protocol:§3.4–3.6 及连接状态处理说明序列号同步、历史重复连接请求、半关闭、同时关闭和 TIME_WAIT,是核对流程与例外的协议依据。
- 国外:Linux man-pages:shutdown:依据 DESCRIPTION 对关闭接收、发送或双向的接口定义,解释正文中 shutdown 与 TCP 半关闭的关系。
相关面经
14 篇得物
MLOps 与 Agent 实习生一个 HTTP 请求从客户端发出,到最终查到数据库里的商品信息,中间链路是什么样的?(追问:握手是谁跟谁握?具体一点)
作业帮
AI 应用开发实习生阿里巴巴
AI Agent 算法**面试官:** TCP为什么有四次挥手?一定需要四次挥手吗?
美团
AI Agent 开发工程师tcp握手挥手 udp
蚂蚁集团
还有什么擅长但是没问到的(我说计算机网络),问 TCP 四次挥手
展开剩余 9 篇面经
百度
请介绍 TCP 三次握手和四次挥手
金山软件
AI 全栈开发工程师微步在线
Java 开发工程师字节跳动
Agent 开发工程师TCP为什么有三次握手四次挥手?一定需要四次挥手吗(这个没答上)?
知乎
后端开发tcp三次握手四次挥手,这一块我有点糟心,忘了
字节跳动
Agent 测评三次握手、四次挥手,为什么三次、四次
字节跳动
AI 应用开发工程师字节跳动
后端开发工程师(AI / Agent 方向)cn:tcp挥手握手。
蚂蚁集团
Agent 应用开发工程师tcp三次握手、四次挥手




