**TCP 三次握手(建立连接)** 和 **四次挥手(断开连接)** 是 TCP 协议中最核心的两个过程,确保可靠的面向连接通信。下面用最清晰的步骤 + 状态变迁 + 目的解释来实现它们。 ### 1. 三次握手(Three-Way Handshake)—— 建立连接 **目的**: - 双方互相确认对方“能发、能收” - 同步初始序列号(ISN / seq),防止旧连接干扰 - 协商一些参数(如窗口大小、MSS 等,可在选项中携带) **过程(客户端主动发起)**: | 步骤 | 发送方 | 标志位 | 序号(seq) | 确认号(ack) | 状态变化(发送方) | 状态变化(接收方) | 含义解释(为什么需要这一步) | |------|----------|------------|-------------|---------------|--------------------------|--------------------------|--------------------------------| | 1 | 客户端 → 服务端 | SYN=1 | seq = x(客户端随机 ISN) | ack = 无 | CLOSED → **SYN_SENT** | LISTEN → **SYN_RCVD** | “我想连接你,我的起始序号是 x” | | 2 | 服务端 → 客户端 | SYN=1, ACK=1 | seq = y(服务端随机 ISN) | ack = x+1 | **SYN_RCVD** | **SYN_SENT** → **ESTABLISHED** | “我也想连接你,我的起始序号是 y,我已收到你的 x” | | 3 | 客户端 → 服务端 | ACK=1 | seq = x+1 | ack = y+1 | **SYN_SENT** → **ESTABLISHED** | **SYN_RCVD** → **ESTABLISHED** | “我收到你的 y 了,连接建立” | **为什么一定是三次,而不是两次?** - 两次只能确认一方能发一方能收(单向确认),无法双向确认。 - 三次才能让双方都确认“对方的发送通道 + 我的接收通道”都正常。 - 防止历史连接的旧 SYN 包误建立连接(通过随机 ISN + 第三次确认)。 **三次握手后状态总结**:双方都进入 **ESTABLISHED** 状态,可以开始双向传输数据。 ### 2. 四次挥手(Four-Way Handshake)—— 断开连接 **目的**: - TCP 是**全双工**(双向独立通道),关闭时需要分别关闭两个方向。 - 确保双方数据都发完再彻底释放资源。 **过程(客户端主动关闭)**(最常见情况,服务端也可以主动关闭,过程对称): | 步骤 | 发送方 | 标志位 | 序号(seq) | 确认号(ack) | 状态变化(发送方) | 状态变化(接收方) | 含义解释(为什么需要这一步) | |------|----------|------------|-------------|---------------|-------------------------------|-------------------------------|--------------------------------| | 1 | 客户端 → 服务端 | FIN=1 | seq = u | ack = 无 | ESTABLISHED → **FIN_WAIT_1** | ESTABLISHED → (不变) | “我客户端不发了(关闭发送)” | | 2 | 服务端 → 客户端 | ACK=1 | seq = v | ack = u+1 | (不变) | → **CLOSE_WAIT** | “收到,我知道了,你不发了” | | 3 | 服务端 → 客户端 | FIN=1 | seq = w | ack = u+1 | → **LAST_ACK** | **CLOSE_WAIT** → **LAST_ACK**(如果服务端也发完) | “我也发完了,不发了(关闭我的发送)” | | 4 | 客户端 → 服务端 | ACK=1 | seq = u+1 | ack = w+1 | **FIN_WAIT_2** → **TIME_WAIT** → (2MSL 后 CLOSED) | **LAST_ACK** → **CLOSED** | “收到,你也关闭了,连接彻底结束” | **关键状态解释**: - **FIN_WAIT_1**:主动关闭方发完 FIN,等待对方 ACK。 - **CLOSE_WAIT**:被动方收到 FIN,知道对方不发了,但自己可能还有数据要发(所以不马上发 FIN)。 - **FIN_WAIT_2**:主动方收到 ACK,但还在等对方的 FIN。 - **LAST_ACK**:被动方发完 FIN,等待最后 ACK。 - **TIME_WAIT**(最重要!):主动关闭方收到最后的 ACK 后进入,持续 **2 × MSL**(Maximum Segment Lifetime,通常 1-4 分钟)。 - 目的①:确保最后 ACK 能到达对方(万一丢了,对方会重发 FIN)。 - 目的②:让本连接的所有残留包在网络中消失,防止干扰新连接(尤其是端口复用时)。 **为什么一定是四次,而不是三次?** - 因为 TCP 是**全双工**,关闭时两个方向独立。 - 被动方收到 FIN 后,可能还有数据要发(不能马上发 FIN),所以 ACK 和 FIN 分开(变成四次)。 - 如果被动方没有剩余数据,ACK 和 FIN 可以合并(实际有时看到“三次挥手”,但规范是四次)。 ### 总结一句话口诀 - **三次握手**:SYN → SYN+ACK → ACK “你好我好大家好,序号对齐,开始发” - **四次挥手**:FIN → ACK → FIN → ACK “我不发了,你呢?……我也好了,再见”