type
status
date
slug
summary
tags
category
icon
password
在计算机网络的世界里,TCP(传输控制协议)以其“可靠性”著称。无论你是浏览网页、发送邮件还是观看视频,背后都离不开 TCP 的保驾护航。
TCP 的可靠性并非凭空而来,而是建立在严格的连接管理机制之上:建立连接时的“三次握手”和断开连接时的“四次挥手”。
本文将抛开枯燥的教科书式叙述,利用清晰的 Mermaid 时序图,带你直观地拆解这两个核心过程。
🎬 前置知识:读懂 TCP 的“暗号”
在看图之前,我们必须掌握 TCP 报文头中几个关键字段的含义。你可以把它们想象成通信双方互相比划的手势或暗号。
1. 核心标志位 (Flags)
这些标志位决定了当前报文的“意图”。
- SYN (Synchronize): 发起连接。如果
SYN=1,代表这方想建立连接并同步序列号。
- ACK (Acknowledgment): 确认收到。如果
ACK=1,代表这方确认收到了对方刚才发来的数据。连接建立后,所有传输的报文 ACK 都必须为 1。
- FIN (Finish): 结束发送。如果
FIN=1,代表这方数据发完了,想关闭连接。
2. 核心计数器
这两个数字用于保证数据按顺序到达且不丢失。
- seq (Sequence Number, 序列号): 我发的这个包,数据是从第几个字节开始的。
- ack (Acknowledgment Number, 确认号): 我期待你下次给我发的包,序列号是多少。(潜台词:在这个号码之前的数据我都收妥了)。
🤝 第一部分:三次握手 (建立连接)
TCP 是面向连接的协议。在传输数据前,双方必须先“打招呼”,确认对方都在线,并初始化双方的序列号。这个过程需要交互三个包,故称“三次握手”。
🗣️ 通俗场景类比
A (你): “喂,老 B,听得到吗?我想和你说话。” (SYN)B (朋友): “听得到,我也想和你说话,你听得到我吗?” (SYN + ACK)A (你): “听得到!那我们开始吧。” (ACK)
📊 Mermaid 时序图解
下面的图清晰地展示了客户端与服务器之间的状态流转和报文交互。
Code snippet
📝 关键步骤解析
- 第一次握手 (SYN):
- 客户端发送一个携带
SYN=1的报文,并随机生成一个初始序列号seq=x。这就像是敲门,告诉服务器:“我想建立连接,我的起始号码是 x”。
- 第二次握手 (SYN + ACK):
- 服务器收到敲门声。为了表示同意,它必须回复一个
ACK=1,并且确认号ack=x+1(意思是:收到 x 了,期待你下次发 x+1)。 - 关键点:同时,服务器自己也要向客户端发起连接同步,所以它也设置了
SYN=1,并生成自己的序列号seq=y。这叫“确认的同时并发起请求”。
- 第三次握手 (ACK):
- 客户端收到了服务器的回复。看到对方同意了(ACK=1),也看到了对方的连接请求(SYN=1)。
- 于是客户端回复最后一个确认包
ACK=1,确认号ack=y+1(意思是:收到 y 了,连接正式建成)。至此,双方都处于ESTABLISHED状态。
👋 第二部分:四次挥手 (断开连接)
天下没有不散的筵席。当数据传输完毕,需要断开连接。
TCP 连接是全双工 (Full-Duplex) 的,意思是数据可以在两个方向上同时传输(A 可以给 B 发,B 也可以同时给 A 发)。因此,关闭连接时,必须两个方向分别关闭,这导致了需要四次交互。
🗣️ 通俗场景类比
A (你): “我的话说完了,我要挂了。” (FIN)B (朋友): “知道了,你先别挂。(但我还有最后几句叮嘱要说完)” (ACK)... (B 继续把剩下的话说完) ...B (朋友): “好了,我也说完了,现在可以挂了。” (FIN)A (你): “好的,拜拜。” (ACK)
📊 Mermaid 时序图解
注意观察图中最大的区别:中间的 ACK 和 FIN 为什么不像握手时那样合并发送?
Code snippet
📝 关键步骤解析
- 第一次挥手 (FIN):
- 主动方(比如客户端)数据发完了,发送
FIN=1,告诉对方:“我没有数据要发了,我想关闭我这边的发送通道”。
- 第二次挥手 (ACK):
- 被动方收到 FIN,立即回复一个
ACK=1确认收到。此时被动方进入 CLOSE_WAIT 状态。 - 为什么不马上发 FIN? 因为被动方手里可能还有没传完的数据。它只是确认了“对方不发了”,但它自己可能还要继续发。
- 第三次挥手 (FIN):
- 等待被动方把所有剩余数据都发完了,它才发送自己的
FIN=1,请求关闭这边的发送通道。
- 第四次挥手 (ACK):
- 主动方收到对方的 FIN,回复最后一个
ACK=1。
🚨 重要细节:TIME_WAIT 状态
细心的你会发现,主动关闭方在发完最后一个 ACK 后,并没有立即变成 CLOSED,而是进入了 TIME_WAIT 状态,要等待 2MSL(最长报文段寿命,通常共几分钟)这么久。
为什么要等?
这是 TCP 的“最后一道保险”。万一第四次挥手的那个 ACK 包在路上丢了怎么办?被动方迟迟收不到确认,就会重发第三次挥手的 FIN 包。如果主动方这时已经关闭跑路了,就没法响应了。TIME_WAIT 就是为了在这段时间内,如果收到了重发的 FIN,还能再补发一个 ACK,确保对方正常关闭。
总结
- 三次握手:为了可靠地建立连接,同步双方的初始序列号。“喂、哎、好”。
- 四次挥手:为了可靠地断开全双工连接,允许单方向关闭。“我没话说了”、“知道了(但我还有话)”、“我也没话说了”、“好的”。
通过 Mermaid 图,希望你能更清晰地理解这几个标志位是如何在网络中“飞来飞去”,从而控制连接状态的。
- Author:Ximou Zhao
- URL:https://ximouzhao.com/article/2d34b0ac-588b-806e-842a-e423f7168908
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!


