TCP为什么采用三次握手而不是二次握手

TCP采用三次握手(Three-way Handshake)而不是二次握手,主要是为了解决网络中的延迟重复报文初始序列号同步问题,确保连接的可靠性和安全性。以下是具体原因:


1. 防止历史重复连接导致的资源浪费

  • 问题场景:如果客户端发送的第一次握手报文(SYN)因网络延迟滞留,客户端会重发一个新的SYN。若采用二次握手,服务端在收到滞留的旧SYN后会直接建立连接(发送SYN-ACK后认为连接已建立),但客户端会忽略这个响应(因为序列号不匹配),导致服务端长期等待,浪费资源。
  • 三次握手的解决:服务端在收到SYN后会等待客户端的第三次ACK确认(第三次握手),只有收到ACK后才真正建立连接。若ACK未到达,服务端会超时关闭连接,避免资源浪费。

场景1:旧SYN 早于 新SYN到达(常规情况)

  1. 客户端发送旧SYN(延迟滞留)

    • 客户端发送 SYN=1, seq=100(旧SYN),但该报文在网络中滞留,未到达服务端。
    • 客户端未收到 SYN-ACK,触发超时重传。
  2. 客户端发送新SYN(正常到达)

    • 客户端重传 SYN=1, seq=300(新SYN),新SYN先到达服务端
    • 服务端回复 SYN-ACK, seq=500, ack=301(确认客户端的 seq=300)。
    • 此时连接尚未建立 !服务端处于 SYN_RCVD 状态,等待客户端的第三次 ACK
  3. 客户端回复第三次ACK

    • 客户端收到 SYN-ACK 后,发送 ACK=1, seq=301, ack=501(确认服务端的 seq=500)。
    • 至此,三次握手完成 ,连接正式建立(服务端进入 ESTABLISHED 状态)。
  4. 滞后的旧SYN到达服务端(关键区别)

    • 旧SYN SYN=1, seq=100 终于到达服务端。
    • 服务端误认为这是一个新连接,回复 SYN-ACK, seq=600, ack=101
    • 但客户端会忽略此 SYN-ACK (因为当前连接已建立,且 ack=101 不匹配客户端的序列号 seq=301)。
    • 服务端因收不到第三次 ACKack=601),会超时关闭这个半连接(避免资源浪费)。

如果是 二次握手 会怎样?

假设TCP采用二次握手(即服务端发送 SYN-ACK 后直接认为连接建立):

  1. 当旧SYN SYN=1, seq=100 到达服务端时:
    • 服务端回复 SYN-ACK, seq=600, ack=101,并立即认为连接已建立
    • 客户端因序列号不匹配(期望 ack=301),忽略此 SYN-ACK
    • 结果:服务端为旧SYN维护了一个无效连接,直到超时。

关键区别

步骤 三次握手 二次握手
服务端收到SYN后的行为 发送 SYN-ACK,等待第三次 ACK 才建立连接。 发送 SYN-ACK 后立即建立连接。
对延迟旧SYN的处理 因无第三次 ACK,服务端会超时关闭无效连接。 服务端会维持无效连接,直到超时(资源浪费)。
安全性 防止历史SYN干扰,确保连接唯一性。 可能因延迟SYN建立多余连接,易受攻击(如SYN洪泛)。

场景2:旧SYN 晚于 新SYN到达

  1. 客户端发送SYN=1, seq=100(旧SYN),延迟滞留。
  2. 客户端重传SYN=1, seq=300(新SYN),新SYN先到达服务端
    • 服务端回复SYN-ACK, seq=500, ack=301,连接正常建立(三次握手完成)。
  3. 延迟的旧SYN到达服务端
    • 服务端误认为是新连接,回复SYN-ACK, seq=600, ack=101
    • 客户端发现ack=101不匹配(当前序列号已是301),忽略该SYN-ACK。
    • 如果是二次握手:服务端会为旧SYN建立另一个无效连接。
    • 三次握手解决 :服务端因收不到ACK(ack=601),不会建立连接。

关键结论

  1. 无论旧SYN早到还是晚到 ,二次握手都会导致服务端可能建立无效连接。
    • 旧SYN早到:客户端不认可,服务端空等。
    • 旧SYN晚到:服务端多建一个无用连接。
  2. 三次握手的核心作用
    • 通过第三次ACK确认双方序列号,过滤所有延迟或重复的SYN
    • 服务端仅在收到ACK后才会真正分配资源,避免资源浪费。

现实类比

假设你两次通知同事开会:

  1. 第一次通知(旧):"周一开会"(延迟未送达)。
  2. 第二次通知(新):"周二开会"(同事收到并回复"收到")。
    • 如果旧通知后来到达
      • 二次握手:同事看到"周一开会"直接准备会议室(浪费资源)。
      • 三次握手:同事会等你确认"周一开会"的回复(但你不会回复,因为已改时间),同事放弃准备。

为什么不能依赖"新SYN一定先到"?

网络延迟是不可控的,可能因路由变化、拥塞、重传等导致报文乱序。TCP的设计必须假设最坏情况(即旧报文可能在任何时候到达),而三次握手是解决这一问题的最小成本方案。


三次握手 vs 二次握手 的核心差异

对比项 三次握手 二次握手
服务端何时认为连接建立? 收到客户端的 第三次 ACK 后才建立 发送 SYN-ACK立即认为连接已建立
无效连接的处理 服务端在 SYN_RCVD 状态等待 ACK未建立完整连接,超时关闭(资源占用较少) 服务端 已认为连接建立ESTABLISHED),但客户端不认可,导致 完全无效的连接 占用资源
资源占用情况 仅维护 半连接队列(SYN队列),占用较少 维护 全连接队列,占用更多资源(如 socket、内存等)
受攻击风险(如SYN洪泛) 更容易防御(未完成握手的连接可快速清理) 更危险(攻击者伪造SYN可快速耗尽服务端连接资源)

为什么说"三次握手更优"?

虽然最终都会超时关闭,但 三次握手 在以下方面更优:

  1. 资源占用更少

    • 三次握手下,服务端在收到 SYN 后仅进入 SYN_RCVD 状态(半连接),占用资源较少。
    • 二次握手下,服务端直接进入 ESTABLISHED 状态,分配完整连接资源(如 socket、缓冲区等),即使客户端不认可,这些资源也会被占用直到超时。
  2. 防止SYN洪泛攻击

    • 攻击者可以伪造大量 SYN 报文,消耗服务端资源。
    • 三次握手 :服务端仅维护半连接队列,超时时间较短(如Linux默认 SYN_TIMEOUT=60s),能更快清理无效请求。
    • 二次握手 :服务端会为每个 SYN 分配完整连接资源,更容易被攻击打满。
  3. 避免"滞留旧SYN"建立无效连接

    • 即使旧 SYN 晚到,三次握手下服务端仍会因收不到 ACK 而关闭,不会建立实际可用的无效连接
    • 二次握手下,服务端会为旧 SYN 分配资源,尽管客户端不认可,但仍可能影响服务端性能(如占用端口、内存等)。

举例说明

假设服务端最大连接数为 1000:

  • 三次握手 :攻击者发送 1000 个 SYN,服务端仅维护 1000 个半连接(SYN_RCVD),不会影响已建立的正常连接。
  • 二次握手 :攻击者发送 1000 个 SYN,服务端直接建立 1000 个无效的 ESTABLISHED 连接,导致正常用户无法访问。

结论

虽然最终都会超时关闭,但 三次握手资源占用、安全性、抗攻击能力 上明显优于二次握手。
核心区别 :三次握手下,服务端在收到 ACK不会分配完整连接资源,而二次握手会过早分配,导致更高的风险。


总结

  • 三次握手的必要性 :通过第三次 ACK 确认双方的初始序列号,并过滤延迟或重复的 SYN
  • 二次握手的问题:服务端无法区分有效连接和延迟的旧SYN,会导致资源浪费。
  • 你的质疑是正确的 :在之前的描述中,"连接建立"的说法不严谨,必须明确第三次 ACK 的作用。

2. 同步双方的初始序列号(ISN)

  • TCP需要通过序列号保证数据有序性和可靠性。三次握手确保双方双向序列号的同步
    1. 客户端发送SYN(携带自己的ISN)。
    2. 服务端回复SYN-ACK(携带自己的ISN并确认客户端的ISN)。
    3. 客户端发送ACK(确认服务端的ISN)。
  • 二次握手的缺陷:若只有两次握手,服务端无法确认客户端是否收到了自己的ISN(即客户端可能未准备好接收数据)。

3. 避免恶意攻击(如SYN洪泛)

  • 二次握手会让服务端在发送SYN-ACK后立即建立连接,攻击者可以伪造大量SYN报文耗尽服务端资源(SYN Flood攻击)。
  • 三次握手的缓解:服务端在收到第三次ACK前仅维护半连接状态(如SYN队列),未完成的连接会被超时清除,降低资源占用。

4. 双向信道可靠性确认

  • TCP是全双工协议,需要确保双向通信 的可靠性。三次握手明确双方均具备收发能力:
    1. 客户端→服务端:SYN证明客户端发送正常。
    2. 服务端→客户端:SYN-ACK证明服务端收发正常。
    3. 客户端→服务端:ACK证明客户端接收正常。

二次握手的问题总结

如果仅用两次握手:

  • 服务端无法区分滞留的旧SYN报文正常新连接
  • 服务端无法确认客户端是否收到了自己的SYN-ACK,可能导致单向连接(客户端未准备好接收数据)。
  • 更易受到资源耗尽攻击。

类比现实场景

想象两人通话:

  1. A:"你能听到我吗?"(SYN)
  2. B:"我能听到你,你能听到我吗?"(SYN-ACK)
  3. A:"我也能听到你!"(ACK)
    此时双方才确认通信正常。若只有前两步,A无法确认B是否听到了自己的第二次回应。

总结:三次握手是平衡可靠性和效率的最小次数,既避免了历史报文干扰,又确保了双向通信的初始序列号同步,同时增强了抗攻击能力。

相关推荐
zly35005 分钟前
Linux(centos)安全狗
linux·运维·服务器
w28306518 分钟前
bypass
网络
scd020841 分钟前
ospf笔记和 综合实验册
网络·智能路由器·hcip
失因1 小时前
Linux 权限管理与 ACL 访问控制
linux·运维·服务器·数据库·centos
玖剹2 小时前
Linux文件操作:从C接口到系统调用
linux·服务器·c语言·c++·笔记·ubuntu
Vdeilae2 小时前
IIS 让asp.net core 项目一直运行
java·服务器·asp.net
Lovyk2 小时前
Linux 系统启动原理
linux·服务器·windows
集成显卡3 小时前
网络安全 | 从 0 到 1 了解 WAF:Web 应用防火墙到底是什么?
网络·安全·web安全
藏在歌词里3 小时前
Linux-Shell脚本基础用法
linux·运维·服务器