TCP三次握手和四次挥手的详细过程?为什么需要三次握手?四次挥手时TIME_WAIT状态的作用?
TCP三次握手详细过程及状态变化
步骤 | 方向 | 报文内容 | 状态变化 |
---|---|---|---|
1 | 客户端 → 服务端 | SYN=1, seq=x(随机ISN) | 客户端进入 SYN_SENT |
2 | 服务端 → 客户端 | SYN=1, ACK=1, seq=y, ack=x+1 | 服务端进入 SYN_RCVD |
3 | 客户端 → 服务端 | ACK=1, seq=x+1, ack=y+1 | 双方进入 ESTABLISHED |
为什么需要三次握手?
(1)防止历史重复连接(旧 SYN 干扰)
如果客户端发送的 SYN 因网络延迟而滞留,后续重传的 SYN 可能导致服务器误认为有多个连接请求。
(2)同步初始序列号(ISN)
TCP 依赖序列号保证数据有序传输,双方需交换初始 seq 值。
两次握手只能确认客户端的 ISN,服务器无法确认自己的 ISN 是否被客户端接收。
(3)避免资源浪费(防止 SYN 洪泛攻击)
如果只有两次握手,服务器在收到 SYN 后直接分配资源,可能被恶意攻击(如 SYN Flood)耗尽资源。
第三次握手确保客户端是真实存在的,减少无效连接占用。
TCP四次挥手(断开连接)
步骤 | 方向 | 报文内容 | 状态变化 |
---|---|---|---|
1 | 主动方(A)→ 被动方(B) | FIN=1, seq=u | A进入 FIN_WAIT_1 |
2 | 被动方(B)→ 主动方(A) | ACK=1, ack=u+1 | B进入 CLOSE_WAIT,A进入 FIN_WAIT_2 |
3 | 被动方(B)→ 主动方(A) | FIN=1, ACK=1, seq=v, ack=u+1 | B进入 LAST_ACK |
4 | 主动方(A)→ 被动方(B) | ACK=1, seq=u+1, ack=v+1 | A进入 TIME_WAIT,B进入 CLOSED |
- | 等待2MSL后 | - | A进入 CLOSED |
为什么需要四次挥手?
TCP是全双工协议,每个方向需单独关闭:
主动方 发送 FIN 表示不再发送数据(但仍可接收)。
被动方 先回复 ACK,确认收到关闭请求。
被动方 处理完剩余数据后,发送自己的 FIN。
主动方 回复 ACK,双方完全关闭。
TIME_WAIT状态的作用
TIME_WAIT 是主动关闭连接的一方(先发 FIN 的一方)在发送最后一个 ACK 后进入的状态,持续 2MSL(Maximum Segment Lifetime,报文最大生存时间,通常为60秒)。
核心作用
确保最后一个ACK到达对端
如果被动方的 FIN 重传(因ACK丢失),主动方能在 TIME_WAIT 期间重新发送 ACK。
让网络中滞留的旧报文失效
等待2MSL时间,确保本次连接的所有数据包都从网络中消失,避免被后续相同四元组(源IP、源端口、目标IP、目标端口)的新连接误收。
TIME_WAIT的影响与优化
问题:高并发场景下,大量 TIME_WAIT 连接会占用端口资源。
解决方案:
开启 SO_REUSEADDR 选项,允许复用 TIME_WAIT 状态的端口。
调整内核参数(如 net.ipv4.tcp_tw_reuse)