计算机网络:TCP 三次握手为什么不是两次?

#计算机网络#操作系统#面试八股

计算机网络:TCP 三次握手为什么不是两次?

TCP 用三次握手建立连接,本质是双方都要确认"我能发、你能收",两次做不到这一点。

1. 两次握手差在哪

两次:A --SYN--> B
      B --SYN+ACK--> A        (B 认为连接已建立)

问题:B 无法确认 A 收到了自己的 SYN+ACK。如果这个包丢了,A 会重发 SYN,而 B 已经认为连接建好、 开始等待数据——资源被白白占用(半开连接)。

三次则补齐了最后一块拼图:

A --SYN(seq=x)-->        B
A <--SYN+ACK(seq=y,ack=x+1)-- B
A --ACK(ack=y+1)-->      B     ← B 收到它才真正建连

2. 防止历史连接

更隐蔽的原因是旧连接的 SYN 迟到:A 发了个早就放弃的 SYN,网络延迟很久后才到 B。 两次握手时 B 直接建连,然后一直等一个不会来的数据;三次握手时 A 会回 RST,B 就不建了。

3. 握手为什么能省一次:SYN 与 ACK 合并

第二步 SYN+ACK 把"确认对方"和"发起自己"合并成一个包,所以最少就是三次。 四次也能建连(SYN、ACK、SYN、ACK),只是多一次往返、多一个 RTT。

4. 常见追问

Q:SYN 队列与 accept 队列? 半连接队列(SYN queue)存收到 SYN、还没完成三次握手的连接;全连接队列(accept queue)存已完成握手、 等待应用 accept() 的连接。SYN flood 打的就是前者,所以有 tcp_syncookies。

Q:为什么挥手要四次? TCP 是全双工,两个方向要各自关闭。收到 FIN 只代表"对方没数据发了",本端可能还有数据要发, 所以 ACK 与 FIN 不能合并(除非本端也正好没数据,那就是三次挥手)。

小结

三次握手是最小的可靠建连次数:两次无法让发起方确认对端收到了自己的确认, 也无法抵御迟到的历史 SYN。记住"两个方向、各需一次确认"就够了。

笔记加载中…