TCP 采用三次握手建立连接的根本原因是为了解决网络通信中的两个核心问题:可靠性和历史连接的消除。两次握手无法满足这些需求,而四次握手虽然理论上可行,但会引入冗余和效率问题。以下是详细分析:
一、两次握手的问题
如果只用两次握手(客户端发送 SYN,服务端回复 SYN-ACK 后直接建立连接),会引发以下问题:
- 无法防止历史连接的干扰
场景:客户端发送了一个旧的 SYN 报文(例如网络延迟导致的重传),服务端收到后回复 SYN-ACK。
问题:若此时客户端认为这是无效连接(例如旧的连接已关闭),会直接忽略服务端的 SYN-ACK。服务端却认为连接已建立,会一直等待客户端发送数据,导致资源浪费(服务端维护一个半开连接)。
- 无法确认客户端的接收能力
场景:服务端发送 SYN-ACK 后,如果客户端未收到该报文(例如网络丢包),客户端不会发送数据。
问题:服务端认为连接已建立,但客户端并未确认,导致单方面连接建立,服务端资源被无效占用。
二、三次握手如何解决问题
三次握手(客户端发送 SYN → 服务端回复 SYN-ACK → 客户端回复 ACK)通过双向确认解决上述问题:
第一次握手(客户端 → 服务端)
客户端发送 SYN 报文,携带初始序列号(seq=x)。
目的:向服务端表明客户端的发送能力正常。
第二次握手(服务端 → 客户端)
服务端回复 SYN-ACK,携带自己的初始序列号(seq=y)和对客户端 SYN 的确认号(ack=x+1)。
目的:
向客户端表明服务端的发送和接收能力正常。
确认客户端的初始序列号。
第三次握手(客户端 → 服务端)
客户端回复 ACK,携带对服务端 SYN 的确认号(ack=y+1)。
目的:
向服务端确认其初始序列号。
消除历史连接:如果客户端收到的是旧 SYN-ACK(来自历史连接),会回复 RST 终止连接,避免服务端误建连接。
三、为什么不需要四次握手?
三次握手已经实现了双向确认:
客户端确认:通过第二次握手(服务端回复 SYN-ACK),客户端确认服务端的发送和接收能力正常。
服务端确认:通过第三次握手(客户端回复 ACK),服务端确认客户端的接收能力正常。
如果使用四次握手(例如客户端再回复一个 ACK 的确认),只是冗余操作,不会带来额外收益,反而增加延迟。
四、三次握手的核心作用
确认双方的通信能力
确保客户端和服务端的发送和接收能力均正常。
同步初始序列号(ISN)
序列号用于标识数据包的顺序和去重。
三次握手确保双方初始序列号的同步,避免数据错乱。
防止历史连接初始化
通过第三次握手,客户端可以终止旧连接的干扰(例如延迟的 SYN 报文)。
五、结论
三次握手是可靠性和效率之间的最佳平衡,既能确保连接可靠性,又避免了冗余操作。