TCP 三次握手与四次挥手
TCP 连接建立与断开的完整过程和状态变化
问题
TCP 三次握手与四次挥手的详细过程、状态变化,以及为什么是三次握手和四次挥手。
解答
三次握手(建立连接)
客户端 服务端
| |
| -------- SYN, seq=x --------> |
| (SYN_SENT) |
| (SYN_RCVD)
| <--- SYN+ACK, seq=y, ack=x+1 --- |
| |
| -------- ACK, ack=y+1 -------> |
| (ESTABLISHED) (ESTABLISHED)
过程说明:
- 第一次握手:客户端发送 SYN 报文(seq=x),进入
SYN_SENT状态 - 第二次握手:服务端收到后,发送 SYN+ACK 报文(seq=y, ack=x+1),进入
SYN_RCVD状态 - 第三次握手:客户端发送 ACK 报文(ack=y+1),双方进入
ESTABLISHED状态
为什么是三次握手?
两次不行的原因:
场景:客户端发送的旧 SYN 报文延迟到达
客户端 服务端
| |
| -------- 旧 SYN --------> | (延迟到达的历史报文)
| |
| <------- SYN+ACK -------- | 服务端以为要建立连接
| |
| (客户端发现是旧连接,不理会) | 服务端白白等待,浪费资源
三次握手的作用:
- 防止历史连接初始化(客户端可以通过第三次握手拒绝)
- 同步双方的初始序列号(ISN)
- 确认双方的收发能力都正常
四次挥手(断开连接)
客户端 服务端
| |
| -------- FIN, seq=u --------> |
| (FIN_WAIT_1) |
| (CLOSE_WAIT)
| <------- ACK, ack=u+1 ------- |
| (FIN_WAIT_2) |
| |
| (服务端可能还有数据要发送) |
| |
| <------- FIN, seq=w -------- |
| (LAST_ACK)
| -------- ACK, ack=w+1 -------> |
| (TIME_WAIT) (CLOSED)|
| |
| 等待 2MSL 后 |
| (CLOSED) |
过程说明:
- 第一次挥手:客户端发送 FIN,进入
FIN_WAIT_1 - 第二次挥手:服务端发送 ACK,进入
CLOSE_WAIT,客户端进入FIN_WAIT_2 - 第三次挥手:服务端发送 FIN,进入
LAST_ACK - 第四次挥手:客户端发送 ACK,进入
TIME_WAIT,服务端收到后进入CLOSED
为什么是四次挥手?
TCP 是全双工通信,每个方向的关闭需要单独进行:
三次握手时:SYN 和 ACK 可以合并发送(服务端同时发 SYN+ACK)
四次挥手时:ACK 和 FIN 不能合并
- 收到 FIN 只表示对方不再发送数据
- 但自己可能还有数据没发完
- 所以先回 ACK,等数据发完再发 FIN
TIME_WAIT 为什么等待 2MSL?
MSL(Maximum Segment Lifetime)是报文最大生存时间。
- 确保最后的 ACK 能到达服务端(如果丢失,服务端会重发 FIN)
- 让本次连接的所有报文在网络中消失,避免影响新连接
关键点
- 三次握手:防止历史连接、同步序列号、确认双方收发能力
- 四次挥手:TCP 全双工,每个方向单独关闭,ACK 和 FIN 不能合并
- TIME_WAIT 等待 2MSL:确保 ACK 到达 + 旧报文消失
- 握手用 SYN,挥手用 FIN,都需要消耗一个序列号
- 服务端 CLOSE_WAIT 状态堆积通常是应用层没有正确关闭连接
目录