标准答案是”防止历史重复连接初始化”。但这题真正的分量在于你能不能用序列号把整个过程讲清楚。
核心:确认双方的双向收发能力
三次握手交换的是 ISN(Initial Sequence Number,初始序列号):
客户端 服务端
|-------- SYN, seq=x -------------------->| 客户端:我能发
|<------- SYN+ACK, seq=y, ack=x+1 --------| 服务端:我能收,我也能发
|-------- ACK, seq=x+1, ack=y+1 --------->| 客户端:我能收
两次握手只能证明客户端能发、服务端能收,服务端无法确认客户端是否能收到自己的包。第三次 ACK 补上这一环,双向信道才都验证完毕。
更关键的:防止历史连接
考虑一个真实场景:客户端发了一个 SYN 后超时重连,旧的 SYN 包延迟到达服务端。
- 两次握手:服务端收到旧 SYN 就直接建立连接、分配资源,然后开始等数据——客户端根本不想连,资源白占
- 三次握手:服务端先回 SYN+ACK,客户端发现 ack 的不是自己当前这个连接,回 RST 拒绝,服务端随即释放
序列号机制让服务端能判断”这是不是一次已经失效的旧请求”。
那四次行不行
理论上可以,但没必要。第二次可以把 SYN 和 ACK 合并成一个包(SYN+ACK),省一次往返。三次是满足需求的最小次数。
常见追问
Q:第三次握手可以带数据吗?
可以。前两次不能,因为连接还没建立,携带数据有安全风险(伪造源 IP 的放大攻击)。第三次时客户端已知服务端可达,放数据是安全的。这也是TCP Fast Open 的优化思路。
Q:SYN 洪水攻击怎么防?
攻击者大量发 SYN 而不回最后一个 ACK,把服务端的半连接队列打满。防御手段:
- SYN Cookies:不立即分配资源,把状态编码进 ISN,收到合法 ACK 再重建
- 缩小
tcp_syn_retries、增大半连接队列 - 前置代理/防火墙做连接代理
Q:ISN 为什么是随机的?
防止序列号预测攻击——如果能猜出 ISN,就可以伪造包插入会话。随机化让预测成本极高。
怎么答出彩
先讲双向收发能力的验证,再讲历史重复连接的场景,最后补一句”三次是满足需求的最小次数,SYN+ACK 合并省了一次往返”。能画出序列号交互的,基本就过了。