TCP三次握手,为什么不能两次或者更多次

TCP三次握手是建立可靠连接的关键机制,其设计是经过严谨权衡的结果,不能简化为两次,也不需要增加为四次或更多。原因如下:

🚫 为什么不能是两次握手?

  1. 防止已失效的连接请求报文导致错误连接(核心原因):

    • 场景: 假设客户端发送了一个SYN报文(Seq=X)请求建立连接,但这个报文在网络中被严重延迟(例如在网络中某个节点长时间滞留)。
    • 客户端处理: 客户端迟迟收不到服务器的响应(SYN-ACK),会认为SYN丢失,于是超时重传一个新的SYN报文(Seq=Y),并与服务器成功完成三次握手,建立连接进行通信,完成后关闭连接。
    • 延迟的SYN到达: 此时,最初那个延迟的SYN报文(Seq=X)终于到达了服务器。
    • 两次握手的灾难: 如果采用两次握手(即服务器收到SYN后直接回复SYN-ACK并进入ESTABLISHED状态):
      • 服务器收到这个迟到的SYN(Seq=X),会认为是一个新的连接请求。
      • 服务器回复SYN-ACK(Ack=X+1, Seq=Z)并立即进入ESTABLISHED状态。
      • 由于是两次握手,服务器认为连接已建立,开始等待数据或发送数据。
    • 问题:
      • 客户端早已关闭了那个本该对应Seq=X的连接,并且当前可能也没有打算与服务器建立新连接。
      • 服务器却为这个“幽灵”连接分配了资源(缓冲区、端口等)并保持打开状态,浪费服务器资源
      • 如果服务器主动发送数据,客户端会收到一个它完全不期望的数据包(因为Seq=X的连接在客户端看来早已失效),客户端会发送RST复位报文,但这之前服务器资源已被无效占用。
    • 三次握手的解决: 在三次握手中,服务器回复SYN-ACK后进入SYN_RCVD状态,并不会立即建立连接。它需要等待客户端的ACK(Ack=Z+1)。对于这个迟到的SYN(Seq=X),客户端收到服务器的SYN-ACK(Seq=Z, Ack=X+1)后:
      • 客户端检查Ack值(X+1),发现这个值并不匹配它最近使用的任何序列号(它最近用的是Y)。因此,客户端会忽略这个SYN-ACK或回复RST
      • 服务器收不到ACK(或收到RST),就不会建立连接,从而避免了无效连接的创建。
  2. 确保双方初始序列号(ISN)被可靠同步:

    • TCP的可靠传输依赖于序列号。通信双方都需要知道对方的初始序列号(ISN)才能正确组装数据和确认。
    • 两次握手中:
      • 客户端发送SYN(包含自身ISN = C)。
      • 服务器发送SYN-ACK(包含自身ISN = S,并确认C+1)。
      • 服务器收到SYN-ACK时知道了客户端的ISN(C),并通过Ack=C+1确认了客户端的SYN。
      • 但是,客户端此时只收到了服务器的ISN(S),它还没有机会确认它! 客户端在两次握手后就进入了ESTABLISHED状态,它知道服务器的ISN是S,但服务器并不知道客户端是否成功收到了这个ISN S。
    • 问题: 如果服务器的SYN-ACK报文丢失,客户端收不到,就不会进入连接状态,也不会发送数据。但服务器在两次握手后已进入ESTABLISHED状态,它会认为连接已建立,并可能开始发送数据(这些数据使用序列号S+1开始)。然而,客户端对这些数据完全没有准备,会感到困惑(收到非期望序列号的数据包),可能导致发送RST断开连接。
    • 三次握手的解决: 客户端的ACK(Ack=S+1)不仅确认了服务器的SYN报文,也明确告知服务器:“我收到了你的ISN S”。只有收到这个ACK,服务器才能确信双方都知道了彼此的ISN,才能安全地进入ESTABLISHED状态并开始发送数据。
  3. 避免服务器资源浪费:

    • 如第1点所述,两次握手会导致服务器在收到SYN后立即分配资源并进入连接状态。如果SYN是泛洪攻击(SYN Flood)或如第1点的延迟报文,服务器资源会被迅速耗尽(SYN Flood攻击正是利用TCP三次握手中服务器在收到SYN后需要等待ACK这一中间状态来耗尽其资源的,但两次握手会让服务器资源消耗得更快更彻底)。
    • 三次握手将资源分配的时机推迟到收到第三次ACK之后,服务器只有在确认客户端是真实存在且确实想建立连接后才分配连接资源,提高了资源利用效率,增强了抗攻击能力

⏳ 为什么不需要四次(或更多)握手?

  • 三次已足够: 经过三次握手:
    1. 客户端发送SYN (Seq=C) -> 证明客户端有发送能力。
    2. 服务器回复SYN-ACK (Seq=S, Ack=C+1) -> 证明服务器有发送和接收能力(收到了C),并告知自身ISN。
    3. 客户端回复ACK (Ack=S+1) -> 证明客户端有接收能力(收到了S),并确认了服务器的ISN。
  • 对称性达成: 三次交换后,双方都发送了SYN(携带自身ISN)并收到了对方的ACK(确认了自身ISN),也都接收到了对方的SYN(得知了对方ISN)并发送了ACK(确认了对方ISN)。双方都明确知道对方已准备好进行可靠通信。
  • 第四次是冗余: 设想第四次握手:服务器再发送一个ACK确认客户端的ACK(Ack=S+1)。这看起来像是确认了确认。但这没有必要
    • 客户端发送的ACK(Ack=S+1)本身已经是对服务器SYN的最终确认。服务器收到这个ACK,就完全确认了客户端已经收到了它的SYN并且知道了它的ISN。
    • 如果这个第四次ACK丢失了,客户端会认为连接已建立(因为它完成了它的三次动作),但服务器还在等待一个不必要的确认,会导致连接状态不一致。
    • 效率降低: 增加一次握手意味着增加一个RTT(Round-Trip Time)的延迟才能建立连接,降低了效率,而带来的额外可靠性微乎其微(TCP的可靠性主要依靠数据传输阶段的确认重传机制保证,建立连接的可靠性由三次握手已充分保障)。
  • 实际优化: 第三次握手(客户端的ACK)通常可以携带应用层数据(如HTTP请求),这进一步减少了建立连接后立即发送数据的延迟(称为捎带确认),使得三次握手在效率上更优。

📌 总结

  • 两次握手不够: 无法解决历史连接问题(导致资源浪费),无法保证双方初始序列号被对方可靠获知(可能导致数据混乱),服务器资源分配过早(易受攻击和无效连接影响)。
  • 四次(或更多)握手不必要: 三次握手已完美达成“双方确认彼此的发送/接收能力和初始序列号”的目标。增加握手次数只会引入不必要的延迟和复杂性,没有带来实质性的可靠性提升。

TCP的三次握手是在保证连接建立的可靠性和防止资源浪费的前提下,实现通信双方初始序列号同步的最精简、最有效的机制。 👏 它是TCP协议可靠性的基石之一。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走过冬季

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值