TCP 三次握手与四次挥手如何进行,为什么要四次挥手?

考查重点:连接建立与双向半关闭。SYN/SYN-ACK/ACK 建连,双方各发 FIN/ACK 关闭发送方向;一方关闭不代表另一方无数据,报文可合并

本题目录

参考答案

核心回答

TCP 三次握手通过 SYN、SYN+ACK、ACK 交换并确认双方的初始序列号,建立连接。关闭时则要分别关闭两个发送方向:一方不再发送,不代表另一方也立刻没有数据,所以通常表现为 FIN、ACK、FIN、ACK 四个报文段。

“四次挥手”不是固定的抓包数量。确认对端 FIN 的 ACK,可以与本端的 FIN 合并;同时关闭、重传或 RST 中止连接,也会产生不同的报文和状态路径。

三次握手如何进行

以 A 主动连接、B 已经监听为例,先忽略报文携带应用数据的情况:

  1. A 发 SYN。 携带自己的初始序列号 x,进入 SYN_SENT。
  2. B 发 SYN+ACK。 用确认号 x+1 确认 A 的 SYN,同时携带自己的初始序列号 y,进入 SYN_RCVD。
  3. A 发 ACK。 用确认号 y+1 确认 B 的 SYN。A 此时进入 ESTABLISHED;B 收到有效确认后,也进入 ESTABLISHED。

SYN 占用一个序列号,所以确认号加一;普通纯 ACK 本身不占用序列号。第三次 ACK 也可以携带数据。

三次的关键是双方都要发送自己的序列号,并获得对方确认。B 在第二次报文中把自己的 SYN 与对 A 的确认合并,所以通常三次就够;如果只有两次,B 还不能确认 A 是否收到了自己的 SYN。

这也用于避免历史重复 SYN 引起错误建连:B 不能只凭收到一个 SYN,就认定对方正在参与这次连接;还需要对方对本次序列号作出有效确认。握手完成只是建立了传输连接,后续可靠传输仍依赖确认、重传、流量控制等机制。

四次挥手如何进行

以 A 先关闭发送方向、B 随后关闭为例:

  1. A 发 FIN,进入 FIN_WAIT_1。 表示 A 的发送数据到此结束。FIN 排在此前的数据之后,也占用一个序列号。
  2. B 确认 FIN,进入 CLOSE_WAIT。 A 收到确认后进入 FIN_WAIT_2。此时 A 到 B 的方向已结束,但 B 仍可向 A 发送剩余数据,这就是半关闭。
  3. B 也发 FIN,进入 LAST_ACK。 本端应用准备结束发送后,B 关闭自己的发送方向,等待确认。
  4. 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 则是正常关闭中的保护等待,不能仅凭数量多就认定泄漏,仍要结合连接频率、端口和资源压力判断。

参考资料

相关面经

14 篇

得物

MLOps 与 Agent 实习生
实习
查看原面经 →
追问
一个 HTTP 请求从客户端发出,到最终查到数据库里的商品信息,中间链路是什么样的?(追问:握手是谁跟谁握?具体一点)

作业帮

AI 应用开发实习生
实习一面、二面
查看原面经 →
为什么四次挥手要四次而不是三次
ok,你说的是适用于一个通用的情况,那假如我等到服务端再发送完数据再ack+fin发回去呢

阿里巴巴

AI Agent 算法
一面
查看原面经 →
**面试官:** TCP为什么有四次挥手?一定需要四次挥手吗?

美团

AI Agent 开发工程师
一面
查看原面经 →
tcp握手挥手 udp

蚂蚁集团

面经合集
查看原面经 →
追问
还有什么擅长但是没问到的(我说计算机网络),问 TCP 四次挥手
展开剩余 9 篇面经

百度

面经合集
查看原面经 →
请介绍 TCP 三次握手和四次挥手

金山软件

AI 全栈开发工程师
一面
查看原面经 →
讲一下TCP三次握手的详细过程,包括ACK报文。
简单讲下四次挥手。

微步在线

Java 开发工程师
秋招一面
查看原面经 →
简单说一下TCP的三次握手四次挥手。
为什么关闭连接需要四次挥手?

字节跳动

Agent 开发工程师
秋招一面
查看原面经 →
TCP为什么有三次握手四次挥手?一定需要四次挥手吗(这个没答上)?

知乎

后端开发
实习一面
查看原面经 →
tcp三次握手四次挥手,这一块我有点糟心,忘了

字节跳动

Agent 测评
一面
查看原面经 →
三次握手、四次挥手,为什么三次、四次

字节跳动

AI 应用开发工程师
日常实习一面
查看原面经 →
三次握手和四次挥手分别解决什么问题?
追问
三次握手的具体顺序是什么?

字节跳动

后端开发工程师(AI / Agent 方向)
日常实习一面、二面、三面、四面
查看原面经 →
cn:tcp挥手握手。

蚂蚁集团

Agent 应用开发工程师
一面
查看原面经 →
tcp三次握手、四次挥手

收录题集

2 个来源,共3 份题集

相关题目

4 题