TCP 三次握手与四次挥手:从原理到状态机一次讲清

前言

TCP 是面向连接的可靠传输协议,连接的建立与释放分别通过「三次握手」和「四次挥手」完成。理解这两个过程,是掌握 TCP 状态机、排查网络问题以及应对面试的基础。

一、为什么 TCP 需要握手

TCP 通信前必须建立连接,核心目的是确认双方具备收发能力、同步初始序列号(ISN),并避免历史连接请求对当前连接造成干扰。序列号负责后续数据包的有序传递与可靠确认,因此双方都需要在连接建立阶段交换各自的初始序列号。

二、TCP 三次握手

三次握手的完整流程如下:

1. 第一次握手:客户端发送 SYN

客户端生成初始序列号 x,向服务器发送 SYN=1, seq=x 报文,随后进入 SYN_SENT 状态。

2. 第二次握手:服务器回复 SYN 和 ACK

服务器收到报文后,为该连接分配资源,生成自己的初始序列号 y,并回复 SYN=1, ACK=1, seq=y, ack=x+1,进入 SYN_RCVD 状态。

3. 第三次握手:客户端发送 ACK

客户端收到后,回复 ACK=1, seq=x+1, ack=y+1,自身进入 ESTABLISHED 状态。服务器收到该 ACK 后也进入 ESTABLISHED 状态,连接建立完成。

用时序图表示如下:

sequenceDiagram participant C as 客户端 participant S as 服务器 C->>S: SYN, seq=x S->>C: SYN+ACK, seq=y, ack=x+1 C->>S: ACK, seq=x+1, ack=y+1

为什么是三次握手而不是两次

两次握手无法可靠同步双方的初始序列号,也无法防止旧的连接请求造成干扰。例如,客户端第一次发送的 SYN 在网络中滞留很久后重新到达服务器,若服务器立即建立连接并回包,客户端却早已放弃该请求,就会产生一个无效连接。三次握手通过让客户端最终确认,避免这种历史报文被误用。

从能力验证角度看,三次握手后双方都能确认:自己的发送能力正常、接收能力正常,对方也具备收发能力。

三、TCP 四次挥手

TCP 支持全双工通信,两个方向的数据发送需要分别关闭,因此释放连接通常需要四次交互。

1. 第一次挥手:主动关闭方发送 FIN

主动关闭方发送 FIN=1, seq=u,进入 FIN_WAIT_1 状态。此后它不再发送数据,但仍可接收对方数据。

2. 第二次挥手:被动关闭方回复 ACK

被动方收到 FIN 后,回复 ACK=1, ack=u+1,进入 CLOSE_WAIT 状态。主动方收到 ACK 后进入 FIN_WAIT_2 状态。此时被动方到主动方的方向可能仍有数据在传输。

3. 第三次挥手:被动关闭方发送 FIN

被动方数据发送完毕后,发送 FIN=1, seq=v,进入 LAST_ACK 状态。

4. 第四次挥手:主动关闭方回复 ACK

主动方收到 FIN 后,回复 ACK=1, ack=v+1,进入 TIME_WAIT 状态,等待 2MSL 时间后关闭。被动方收到 ACK 后立即关闭连接。

用时序图表示如下:

sequenceDiagram participant C as 主动关闭方 participant S as 被动关闭方 C->>S: FIN, seq=u S->>C: ACK, ack=u+1 S->>C: FIN, seq=v C->>S: ACK, ack=v+1

为什么是四次挥手而不是三次

被动方收到 FIN 时,可能还有数据没有发送完毕,因此它需要先单独回复 ACK 表示「我收到了关闭请求」,等数据全部发送完成后再发送 FIN。这两个动作无法合并,所以挥手通常为四次。如果被动方恰好没有数据要发送,第二次的 ACK 和第三次的 FIN 可以合并,此时会退化为三次挥手。

TIME_WAIT 状态的作用

主动关闭方在发送最后一个 ACK 后会进入 TIME_WAIT 状态,并等待 2MSL 的时间,原因主要有两点:

  • 确保最后的 ACK 能被对方收到:如果该 ACK 丢失,被动方会重传 FIN,主动方仍有机会再次回复 ACK。
  • 让旧连接的数据包在网络中自然消失:避免同源同目的端口的旧数据包进入新连接,造成数据混乱。

四、常见问题梳理

问题 简要解释
第三次握手失败会怎样 服务器在 SYN_RCVD 状态重发 SYN+ACK,超过次数后释放半连接资源。
SYN 洪泛攻击如何防范 常见手段包括限制半连接数量、缩短 SYN 超时时间、启用 SYN Cookie 等。
为什么 TIME_WAIT 是 2MSL 保证最后一个 ACK 可达,并让旧连接报文在网络中消散。
挥手一定是四次吗 不一定,若被动方无数据发送,可将第二次和第三次合并,变为三次挥手。

五、总结

三次握手解决的是「连接能不能建立、初始序列号如何同步」的问题,四次挥手解决的是「两个方向的数据如何安全关闭」的问题。抓住状态变化这条主线,再结合实际抓包观察 SYN、FIN、ACK 报文,就能更直观地理解整个 TCP 连接的生命周期。

相关推荐
回眸&啤酒鸭1 小时前
【回眸】OpenSwarm 多智能体协作系统实战指南
大数据·前端·人工智能
用户69371750013841 小时前
2026,程序员的时代拐点到了
android·前端·后端
大龄秃头程序员1 小时前
一次 iBeacon + BLE 无感解锁方案的实现记录
前端
小兔子2 小时前
Python 的 GIL 与 free-threading:3.13 之后「去 GIL」走到哪一步了
前端
IT_陈寒2 小时前
SpringBoot自动配置差点让我加班到凌晨
前端·人工智能·后端
guslegend3 小时前
脚手架原理与本地调试:从 bin 软链接到 npm link
前端·npm·node.js·脚手架·前端工程化
海码事务所3 小时前
Google Play 新个人开发者账号上架指南:12 人连续 14 天封闭测试怎么做?
前端
田威AI3 小时前
图片内文字翻译的规格:输入输出、保真、自动化、时间与费用
前端·计算机视觉
不可能片场3 小时前
命令行中文变问号 我用环境变量救了场
前端·electron
lerhxx4 小时前
AI 应用中的上下文管理 —— 从"上下文窗口"到"分层压缩"的工程实践
前端·javascript