在TCP三次握手过程中,“第二次握手”是指服务器对客户端发起的连接请求作出响应的步骤。具体来说:
- 客户端首先发送一个SYN(Synchronize)报文(第一次握手),其中包含初始序列号(ISN),表示“我想建立连接”。
- 服务器收到SYN后,回复一个SYN+ACK报文(第二次握手):
- ACK(Acknowledgment):确认号 = 客户端SYN中的序列号 + 1,表示“我收到了你的SYN”;
- SYN:同时携带自己的初始序列号(服务器的ISN),表示“我也准备好了,这是我的起始序号”。
- 此报文标志位中SYN=1、ACK=1,是同步与确认的合并响应。
这一步完成后,服务器进入 SYN_RCVD 状态,等待客户端的最终确认。
客户端 → 服务器:SYN (seq=x) // 第一次握手 服务器 → 客户端:SYN+ACK (seq=y, ack=x+1) // 第二次握手 ✅ 客户端 → 服务器:ACK (seq=x+1, ack=y+1) // 第三次握手注意:SYN 和 ACK 都是 TCP 头部中的控制标志位;SYN 报文虽不携带应用层数据,但仍消耗一个序列号(即SYN占用1字节序号空间)。
TCP三次握手不能简化为两次握手,根本原因在于无法在不可靠的网络中可靠地同步双方的初始序列号(ISN)并防止历史重复连接(old duplicate connection)的干扰。两次握手会导致以下关键问题:
❌ 主要问题:无法防止“失效的旧SYN”引发错误连接(即“迷途重复连接”问题)
- 假设客户端发送SYN(seq=x)建立连接,但该SYN在网络中严重延迟,未被服务器及时响应或丢弃;
- 客户端超时重传,新SYN(seq=x’)成功完成两次握手(客户端→SYN,服务器→SYN+ACK),连接建立并通信后关闭;
- 此时,滞留的旧SYN(seq=x)突然到达服务器——若仅两次握手,服务器收到后会直接回复SYN+ACK(ack=x+1),并认为新连接已建立(进入ESTABLISHED状态);
- 但客户端并未发起该连接,且不期望此响应,不会发送ACK,也不会处理后续数据;而服务器却维持半打开/错误连接,浪费资源,甚至可能误收后续伪造数据。
✅ 三次握手通过客户端最终确认(第三次ACK)强制要求:
“只有当我明确收到了你的SYN+ACK,并确认你的ISN(y)后,我才发ACK;否则这个连接不成立。”
这确保了:
- 双方都确认了对方的初始序列号(客户端知悉服务器ISN=y,服务器知悉客户端ISN=x);
- 客户端对服务器SYN的显式应答,可过滤掉因网络延迟导致的旧SYN重放;
- 服务器必须等到客户端ACK才进入ESTABLISHED状态,避免单方面维持无效连接。
🔍 补充:两次握手还无法解决“双方同时发起连接”(simultaneous open)的协调问题(虽少见,但协议需健壮支持)
两次握手(❌ 不安全): Client → SYN (seq=x) Server → SYN+ACK (seq=y, ack=x+1) → 连接即建立! → 但若此SYN+ACK丢失,或旧SYN迟到,服务器已“自以为连接就绪”,而客户端一无所知。 三次握手(✅ 安全): Client → SYN (seq=x) Server → SYN+ACK (seq=y, ack=x+1) Client → ACK (seq=x+1, ack=y+1) ← 关键!只有此时双方才真正同步并就绪。因此,三次握手是保证连接可靠性、安全性与状态一致性的最小必要机制。