惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Scott Helme
Scott Helme
N
Netflix TechBlog - Medium
AI
AI
Security Latest
Security Latest
GbyAI
GbyAI
P
Proofpoint News Feed
Y
Y Combinator Blog
A
Arctic Wolf
G
Google Developers Blog
U
Unit 42
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
Vulnerabilities – Threatpost
Know Your Adversary
Know Your Adversary
Cisco Talos Blog
Cisco Talos Blog
T
Tor Project blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
L
Lohrmann on Cybersecurity
C
CERT Recently Published Vulnerability Notes
C
Check Point Blog
B
Blog RSS Feed
The GitHub Blog
The GitHub Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
Cisco Blogs
云风的 BLOG
云风的 BLOG
NISL@THU
NISL@THU
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Security Blog
Microsoft Security Blog
T
The Blog of Author Tim Ferriss
阮一峰的网络日志
阮一峰的网络日志
Latest news
Latest news
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
WordPress大学
WordPress大学
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
The Hacker News
The Hacker News
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
Project Zero
Project Zero
博客园_首页

博客园 - Lemo_wd

flutter —— iOS 的构建与分发 flutter —— 理解 iOS 的依赖管理 wireguard 入门 k3s 基础 —— 将 traefik 替换为 ingress-nginx Pr 入门 给 ssh 私钥文件配置统一口令 滚动部署零碎笔记1 Clickhouse 物化视图与投影 Clickhouse 主键索引 Clickhouse 核心概念 ClickHouse 案例学习 —— 使用 ClickHouse 探索 GitHub 统计信息 linux Tun/Tap 虚拟网卡 Clickhouse 的 kafka Engine 集成 Clickhouse 表引擎 —— MergeTree 局域网中的设备间的流量转发 d3.js 构建股权架构图并绘制双向节点树 final cut pro 入门 d3.js 构建股权架构图并绘制股权百分比 flutter 的滚动控制 —— 滚动类组件的内部与整体滚动
为什么 TCP 是3次握手4次挥手?
Lemo_wd · 2025-09-23 · via 博客园 - Lemo_wd

① 为什么是三次握手?(A: 客户端,B: 服务器)

TCP连接是全双工的,意味着数据在两个方向上可以同时传输。因此,建立连接的关键是确保双方都具有发送和接收的能力,并且要同步双方的初始序列号(Sequence Number, SN),这是TCP可靠性传输的基石。

  1. 第一次握手 (SYN):客户端发送一个SYN包(SYN=1)到服务器,并选择一个初始序列号 seq = x。这表示:“你好服务器,我想建立连接。我的初始序列号是x。”

意义:客户端证明了自己有发送能力。

  1. 第二次握手 (SYN-ACK):服务器收到SYN包后,必须进行确认。它发送一个SYN-ACK包(SYN=1, ACK=1),确认号为 ack = x + 1,同时自己也选择一个初始序列号 seq = y。这表示:“收到你的请求了(x),我同意建立连接。我的初始序列号是y。”

意义:服务器证明了自己有接收能力和发送能力。

  1. 第三次握手 (ACK):客户端收到服务器的SYN-ACK包后,再次发送一个ACK包(ACK=1),确认号为 ack = y + 1,序列号为 seq = x + 1。这表示:“收到你的同意了(y),连接已建立,我们可以开始发送数据了。”

意义:客户端证明了自己有接收能力。

② 为什么是四次挥手?(A: 主动关闭方,B: 被动关闭方)

TCP连接是全双工的,这意味着数据在两个方向上独立传输。因此,关闭连接需要分别关闭这两个方向的数据流。

  1. 第一次挥手 (FIN):主动关闭方(比如客户端)发送一个FIN包(FIN=1),序列号为 seq = u。这表示:“我这边没有数据要发送了,准备关闭连接。”(即关闭客户端到服务器的数据通道)

意义:主动方通知对方,我发完了。

  1. 第二次挥手 (ACK):被动关闭方(服务器)收到FIN后,发送一个ACK包(ACK=1),确认号为 ack = u + 1。这表示:“知道你发完了。”

意义:被动方确认收到了主动方的关闭请求。此时,从主动方到被动方这个方向的连接就关闭了。但服务器可能还有数据没发完。

  1. 第三次挥手 (FIN):当被动方也准备好了关闭连接时(数据处理完了),它发送一个FIN包(FIN=1),序列号为 seq = w。这表示:“我这边也发完了,我也要关闭了。”(即关闭服务器到客户端的数据通道)

意义:被动方发起自己方向的关闭请求。

  1. 第四次挥手 (ACK):主动关闭方收到FIN后,发送一个ACK包(ACK=1),确认号为 ack = w + 1。这表示:“知道你也要关了,再见。”

意义:主动方确认被动方的关闭请求。此时,整个TCP连接才正式关闭。

③ 可以将第二次挥手的ACK和第三次挥手的FIN合并成一个包发送吗?

可以,但前提是对方没有数据要发送了。在很多情况下,服务器收到FIN时可能正在发送数据,所以ACK先发出去,等所有数据发完再发FIN,这就自然形成了四次挥手。Linux内核中有一个选项 tcp_fin_timeout 来控制这个行为。

④ tcp_fin_timeout 作用是?

TCP 四次挥手中主动关闭方的状态变化:

  1. 主动关闭方(如 Client)发送 FIN 包,进入 FIN-WAIT-1 状态。
  2. 收到对端(如 Server)回应的 ACK 包后,进入 FIN-WAIT-2 状态。此时,tcp_fin_timeout 计时器开始生效。
  3. 在 FIN-WAIT-2 状态,主动关闭方等待对端发送它自己的 FIN 包(即第三次挥手)。
  4. 有两种可能的结果:
    正常情况:在 tcp_fin_timeout 超时之前,收到了对端的 FIN 包。主动关闭方回复 ACK(第四次挥手),然后连接直接进入 TIME-WAIT 状态,FIN-WAIT-2 状态结束。
    异常情况:对端因为某种原因(如程序崩溃、进程被杀、网络丢包等)始终没有发送 FIN 包。此时,tcp_fin_timeout 计时器到期,内核会强制将这条处于 FIN-WAIT-2 状态的连接关闭,释放相关资源(如内存、端口等)。

为什么要设置这个超时?
如果没有这个超时限制,而对端又永远不发送 FIN 包,那么主动关闭方的连接就会永远停留在 FIN-WAIT-2 状态。每一个这样的连接都会占用系统的内存和一个文件描述符。如果大量连接出现这种情况,就会耗尽系统资源,导致新的连接无法建立,形成一种拒绝服务(DoS)状态。