一、TCP 三次握手(建立连接)
目的:确保客户端和服务端具备双向通信能力(验证双方发送/接收功能正常)。
流程图解
plaintext
客户端 服务端 | | | 1. SYN=1, Seq=x | |--------------------------->| | | | 2. SYN=1, ACK=1, Seq=y, Ack=x+1 | |<---------------------------| | | | 3. ACK=1, Seq=x+1, Ack=y+1 | |--------------------------->| | | | 连接建立完成! |
分步解析
-
第一次握手(SYN)
-
客户端 → 服务端
-
发送:
SYN=1
(请求建立连接) +Seq=x
(随机序列号) -
客户端状态:
SYN_SENT
(等待确认)
-
-
第二次握手(SYN + ACK)
-
服务端 → 客户端
-
发送:
-
SYN=1
(同意建立连接) -
ACK=1
(确认收到请求) -
Seq=y
(服务端随机序列号) -
Ack=x+1
(期望下次收到x+1
的数据)
-
-
服务端状态:
SYN_RCVD
(已收到请求,等待确认)
-
-
第三次握手(ACK)
-
客户端 → 服务端
-
发送:
-
ACK=1
(确认服务端的响应) -
Seq=x+1
(序列号延续) -
Ack=y+1
(期望下次收到y+1
的数据)
-
-
双方状态:
ESTABLISHED
(连接已建立!)
-
✅ 为什么需要三次?
防止历史连接干扰(重复的 SYN 包会被丢弃)
确保双方收发能力正常(最少需三次交互验证)
二、TCP 四次挥手(断开连接)
目的:安全关闭双向通信通道(双方独立关闭自己的数据流)。
流程图解
plaintext
客户端 服务端 | | | 1. FIN=1, Seq=u | |--------------------------->| | | | 2. ACK=1, Seq=v, Ack=u+1 | |<---------------------------| | (客户端→服务端方向关闭) | | | | 3. FIN=1, ACK=1, Seq=w, Ack=u+1 | |<---------------------------| | | | 4. ACK=1, Seq=u+1, Ack=w+1 | |--------------------------->| | | | 连接完全关闭! |
分步解析
-
第一次挥手(FIN)
-
客户端 → 服务端
-
发送:
FIN=1
(请求关闭连接) +Seq=u
(当前序列号) -
客户端状态:
FIN_WAIT_1
(等待确认)
-
-
第二次挥手(ACK)
-
服务端 → 客户端
-
发送:
ACK=1
(确认关闭请求) +Ack=u+1
-
服务端状态:
CLOSE_WAIT
(准备关闭己方连接) -
客户端状态:
FIN_WAIT_2
(等待服务端关闭)
-
-
第三次挥手(FIN)
-
服务端 → 客户端
-
发送:
FIN=1
(服务端请求关闭) +ACK=1
(确认) +Seq=w
-
服务端状态:
LAST_ACK
(等待最后确认)
-
-
第四次挥手(ACK)
-
客户端 → 服务端
-
发送:
ACK=1
(确认关闭) +Ack=w+1
-
客户端状态:
TIME_WAIT
(等待 2MSL 时间后关闭) -
服务端状态:
CLOSED
(立即关闭)
-
⏳ TIME_WAIT 的作用
等待 2MSL(报文最大生存时间,通常 1~4 分钟)
目的:确保服务端收到 ACK(若丢失,服务端会重发 FIN)
防止旧连接数据干扰新连接
三、关键问题解答
-
为什么握手是三次,挥手是四次?
-
握手时:服务端的
SYN+ACK
可合并为一次发送 -
挥手时:服务端的
ACK
和FIN
需分开发送(因为需先确认关闭,再处理剩余数据)
-
-
如果握手只有两次会怎样?
-
客户端无法确认服务端是否收到自己的响应(可能导致连接失败)
-
-
为什么需要 TIME_WAIT?
-
防止最后一个 ACK 丢失(服务端重发 FIN 时可响应)
-
让旧连接的报文在网络中消失(避免与新连接混淆)
-
总结:
-
三次握手 = 验证双向通信能力(防历史连接干扰)
-
四次挥手 = 安全关闭双向通道(处理未完成数据 + 确保可靠终止)
-
核心思想:通过序列号(Seq)和确认号(Ack)保证数据顺序与完整性!
如果此文章对您有所帮助,那就请点个赞吧,收藏+关注 那就更棒啦,十分感谢!!!