前言
本文是博主根据自身理解,尽量用最通俗的形式解释TCP的三次握手四次挥手。
一、三次握手:为什么不是两次或四次?
1. 三次握手过程
- SYN:客户端发送
SYN=1, seq=x
(我要连接) - SYN+ACK:服务器回复
SYN=1, ACK=1, seq=y, ack=x+1
(同意连接,并同步自己的序号) - ACK:客户端发送
ACK=1, seq=x+1, ack=y+1
(确认连接)
2. 为什么必须三次?
-
防止历史连接混乱
如果只有两次握手,网络延迟可能导致旧的SYN
包到达服务器。服务器会误认为客户端发起新连接,但客户端实际已放弃旧连接,导致资源浪费。 -
确保双方能力对等
第三次握手是客户端对服务器的确认。只有完成三次握手,双方才能确认彼此发送和接收能力正常。
形象比喻:
我们两个人打电话,我们需要确定,我们双方是否都能够听到对方的声音。
A打电话给B:
- A问:“能听到吗?”(SYN)
- B回答:“能,你能听到我吗?”(SYN+ACK)
- A说:“能!”(ACK)
此时双方确认通话通道畅通。
二、四次挥手:为什么不能合并为三次?
1. 四次挥手过程
- FIN:主动关闭方发送
FIN=1
(我要断开) - ACK:被动方回复
ACK=1
(收到请求,但可能还有数据要发) - FIN:被动方处理完数据后发送
FIN=1
(我也要断开) - ACK:主动方回复
ACK=1
(确认断开)
2. 为什么必须四次?
-
全双工通信的独立性
TCP连接是双向通道(客户端→服务器,服务器→客户端)。四次挥手确保两个方向独立关闭:- 主动方关闭
发送通道
(发FIN)。 - 被动方关闭
接收通道
(回ACK)。 - 被动方处理完数据后关闭自己的
发送通道
(发FIN)。 - 主动方关闭
接收通道
(回ACK)。
- 主动方关闭
-
避免数据丢失
被动方收到第一个FIN
时,可能仍有数据未发送完毕。四次挥手允许被动方在发送FIN
前处理残留数据。
典型场景:
我们电话聊天,有一方想要结束对话了,但是我们不知道对方还有没有重要的事情需要交代,所以要先告诉对方我想挂断,然后看看对方是否还要交代东西,最后对方表示我没话了再挂断。
A和B视频通话后挂断:
- A说:“我不想聊了,要挂电话了”(FIN)
- B说:“好的,但等我把重要的事情说完”(ACK)
- B保存完毕:“我说完了挂了吧”(FIN)
- A回应:“收到”(ACK)
至此双方彻底断开。
三、常见疑问解答
Q1:为什么不能将第2、3步合并为一次挥手(三次挥手)?
- 如果被动方在收到
FIN
后立即同时发送ACK
和FIN
,意味着被动方必须立刻关闭,无法处理剩余数据。而现实中,被动方可能需要时间处理缓存数据。
Q2:为什么握手能三次而挥手必须四次?
- 握手时,服务器可以合并SYN和ACK(SYN+ACK包),因为此时没有数据传输压力。
- 挥手时,被动方的
ACK
和FIN
无法合并,因为中间可能有数据待处理。
Q3:有没有例外情况?
- 同时关闭:如果双方同时发送
FIN
,会进入CLOSING
状态,最终通过两次ACK确认。但这种情况罕见,标准流程仍为四次挥手
四、总结
- 三次握手:确保双方收发能力正常,避免历史连接干扰。
- 四次挥手:保障双向通道独立关闭,允许处理残留数据。
- 设计本质:在不可靠的IP网络上实现可靠通信,每一步都针对网络延迟、丢包和数据完整性设计。