第一种:小白通俗易懂版
三次握手(建立连接)——就像打电话前的确认
核心目的:确保双方都能正常“发消息”和“收消息”。
步骤拆解(用打电话举例):
-
第一次握手(客户端 → 服务器)
- 客户端发送
SYN
(同步信号):相当于你打电话给对方说:“喂,能听到吗?” - 作用:告诉服务器“我想和你建立连接”,并带上自己的初始序号(比如随机数100)。
- 客户端发送
-
第二次握手(服务器 → 客户端)
- 服务器回复
SYN-ACK
(同步-确认信号):对方回答:“能听到!你能听到我吗?” - 作用:
ACK=101
:确认收到了客户端的SYN(100+1);SYN=200
:带上服务器的初始序号(比如200)。
- 服务器回复
-
第三次握手(客户端 → 服务器)
- 客户端发送
ACK
(确认信号):你回答:“我也能听到你!” - 作用:
ACK=201
确认收到了服务器的SYN(200+1)。 - 此时连接建立:双方确认彼此都能正常收发消息。
- 客户端发送
为什么必须三次?
- 如果是两次握手:假设客户端第一次发送的SYN因网络延迟很久才到服务器,服务器会误以为这是新请求,直接建立连接,但客户端早已放弃,导致服务器空等(资源浪费)。
- 三次握手解决了“历史遗留的无效请求”问题。
四次挥手(断开连接)——像礼貌挂电话
核心目的:双方确认数据都已发送完毕,安全断开。
步骤拆解(用挂电话举例):
-
第一次挥手(主动方 → 被动方)
- 主动方发送
FIN
(结束信号):你说:“我说完了,要挂电话了。” - 作用:主动方不再发送数据,但还能接收数据。
- 主动方发送
-
第二次挥手(被动方 → 主动方)
- 被动方回复
ACK
:对方说:“好的,我知道了。” - 作用:确认收到FIN,但被动方可能还有数据没发完,继续发送。
- 被动方回复
-
第三次挥手(被动方 → 主动方)
- 被动方发送
FIN
:对方说:“我也说完了,可以挂了。” - 作用:被动方数据发送完毕,通知主动方关闭连接。
- 被动方发送
-
第四次挥手(主动方 → 被动方)
- 主动方回复
ACK
:你说:“好的,再见!” - 作用:确认收到被动方的FIN,连接彻底关闭。
- 主动方回复
为什么需要四次?
- TCP是全双工的,两边可独立收发数据。
- 第一次挥手后,主动方不再发送数据,但被动方可能还在发送剩余数据(需要时间),所以被动方的FIN和ACK是分开发送的。
总结对比
三次握手 | 四次挥手 | |
---|---|---|
目的 | 建立可靠连接 | 安全断开连接 |
次数 | 3次 | 4次 |
关键点 | 解决历史SYN问题 | 等待对方数据发送完毕 |
比喻 | 打电话前的“喂喂喂”确认 | 礼貌的“再见”和确认 |
小白记忆法:
- 三次握手:你说 → 对方答 → 你确认。
- 四次挥手:你说要挂 → 对方同意 → 对方说要挂 → 你同意。
第二种:官方严谨版
一、三次握手(Three-Way Handshake)—— 建立连接
核心目标:双方同步初始序列号(Sequence Number),确认通信能力。
官方流程步骤:
-
第一次握手(SYN)
- 客户端发送一个 SYN 报文(
SYN=1
),并携带一个随机生成的 初始序列号(ISN)(例如seq=x
)。 - 客户端状态:
SYN-SENT
(等待服务器确认)。
- 客户端发送一个 SYN 报文(
-
第二次握手(SYN + ACK)
- 服务器收到 SYN 后,回复 SYN + ACK 报文:
SYN=1
(表示同步)ACK=1
(表示确认)ack=x+1
(确认客户端的序列号x
)- 并携带服务器的 初始序列号(ISN)(例如
seq=y
)。
- 服务器状态:
SYN-RECEIVED
(已发送SYN-ACK,等待客户端确认)。
- 服务器收到 SYN 后,回复 SYN + ACK 报文:
-
第三次握手(ACK)
- 客户端收到 SYN-ACK 后,回复 ACK 报文:
ACK=1
ack=y+1
(确认服务器的序列号y
)。
- 双方状态:进入
ESTABLISHED
(连接已建立),开始传输数据。
- 客户端收到 SYN-ACK 后,回复 ACK 报文:
协议细节:
- 序列号(Sequence Number):随机生成,防止历史报文被劫持。
- ACK 值:总是对方序列号
+1
,表示期望下次收到的数据起始位置。 - 为什么必须三次?
- 确保双方都能 发送和接收 数据(全双工)。
- 防止旧的重复 SYN 报文导致连接错误(RFC 9293 明确要求三次)。
二、四次挥手(Four-Way Handshake)—— 断开连接
核心目标:双方确认数据已发送完毕,安全释放连接资源。
官方流程步骤:
-
第一次挥手(FIN)
- 主动关闭方(如客户端)发送 FIN 报文(
FIN=1
),携带当前序列号(例如seq=u
)。 - 主动方状态:
FIN-WAIT-1
(等待对方确认)。
- 主动关闭方(如客户端)发送 FIN 报文(
-
第二次挥手(ACK)
- 被动关闭方(如服务器)收到 FIN 后,回复 ACK 报文:
ACK=1
ack=u+1
(确认客户端的 FIN)。
- 被动方状态:
CLOSE-WAIT
(等待自身数据发送完毕)。 - 主动方状态:
FIN-WAIT-2
(等待被动方的 FIN)。
- 被动关闭方(如服务器)收到 FIN 后,回复 ACK 报文:
-
第三次挥手(FIN)
- 被动关闭方数据发送完毕后,发送 FIN 报文(
FIN=1
),携带序列号(例如seq=v
)。 - 被动方状态:
LAST-ACK
(等待最后一次确认)。
- 被动关闭方数据发送完毕后,发送 FIN 报文(
-
第四次挥手(ACK)
- 主动关闭方收到 FIN 后,回复 ACK 报文:
ACK=1
ack=v+1
(确认服务器的 FIN)。
- 主动方状态:进入
TIME-WAIT
(等待 2MSL 时间,确保对方收到 ACK),最终关闭。 - 被动方状态:收到 ACK 后关闭连接。
- 主动关闭方收到 FIN 后,回复 ACK 报文:
协议细节:
- TIME-WAIT 状态:主动方等待 2MSL(报文最大生存时间),确保被动方收到 ACK,防止旧报文干扰新连接。
- 为什么需要四次?
- TCP 是全双工协议,双方需独立关闭自己的发送通道。
- 被动方可能仍有数据要发送,需先发 ACK 确认,再发 FIN 终止。
三、官方流程图解
三次握手(建立连接):
Client Server
|-------- SYN (seq=x) ----------->|
|<--- SYN-ACK (seq=y, ack=x+1) ---|
|-------- ACK (ack=y+1) -------->|
四次挥手(断开连接):
Client Server
|-------- FIN (seq=u) ------------>|
|<------- ACK (ack=u+1) ----------|
|<------- FIN (seq=v) ------------|
|-------- ACK (ack=v+1) --------->|
四、RFC 关键点总结
- 三次握手:
- 避免历史 SYN 报文导致的连接混乱(RFC 9293 Section 3.4)。
- 四次挥手:
- 确保数据完整性和可靠性(RFC 9293 Section 3.5)。
- 序列号随机性:防止攻击者预测序列号(RFC 6528)。
通过三次握手和四次挥手,TCP 实现了 面向连接的可靠通信,这也是互联网数据传输的基石。