握手

三次握手流程

第一步:客户端发送 SYN(同步请求)

  • 报文内容

    • 标志位:SYN=1(请求建立连接)

    • 序列号(Sequence Number):seq=x(随机生成的初始值)

  • 客户端状态SYN_SENT

  • 作用:客户端向服务器声明自己的初始序列号(x),请求建立连接。

第二步:服务器回复 SYN-ACK(同步确认)

  • 报文内容

    • 标志位:SYN=1(接受连接请求) + ACK=1(确认客户端的 SYN)

    • 序列号:seq=y(服务器随机生成的初始值)

    • 确认号(Acknowledgment Number):ack=x+1(期望收到客户端下一个报文的序列号)

  • 服务器状态SYN_RECEIVED

  • 作用

    1. 确认客户端的 SYN(通过 ack=x+1

    2. 声明服务器的初始序列号(y

第三步:客户端发送 ACK(最终确认)

  • 报文内容

    • 标志位:ACK=1

    • 序列号:seq=x+1(客户端初始序列号 +1)

    • 确认号:ack=y+1(期望收到服务器下一个报文的序列号)

  • 双方状态ESTABLISHED

  • 作用

    1. 确认服务器的 SYN(通过 ack=y+1

    2. 连接正式建立,双方可开始传输数据。


关键机制解析

  1. 序列号(Sequence Number)

    • 初始值为随机数(防止历史报文干扰)

    • 后续数据按序列号顺序传输,确保可靠性。

  2. 为什么需要三次握手?

    • 防止已失效的连接请求:若只有两次握手,网络中滞留的旧 SYN 报文可能被服务器误认为新请求,导致资源浪费。

    • 双向确认:确保双方均确认对方的发送和接收能力正常。


抓包示例(Wireshark视角)

No.  Time        Source          Destination     Protocol Info
1    0.000000    Client_IP       Server_IP       TCP      SYN (seq=100)
2    0.000042    Server_IP       Client_IP       TCP      SYN, ACK (seq=200, ack=101)
3    0.000078    Client_IP       Server_IP       TCP      ACK (seq=101, ack=201)
  • 观察要点

    • 三次交互的 SYNACK 标志位变化

    • 序列号(seq)和确认号(ack)的递增逻辑

    • 时间间隔(RTT,反映网络延迟)


常见问题与故障场景

  1. 握手失败原因

    • SYN未到达:防火墙拦截、网络不通

    • SYN-ACK未返回:服务器未监听端口、负载过高

    • ACK丢失:客户端未正确处理 SYN-ACK

  2. SYN洪泛攻击(SYN Flood)

    • 攻击者伪造大量 SYN 请求但不回复 ACK,耗尽服务器资源。

    • 防御:SYN Cookie 技术、限制半开连接数。


扩展思考

  • 四次挥手(连接终止):通过 FINACK 报文分四次交互,确保数据完整传输。

  • TCP Fast Open(TFO):优化握手流程,允许在首次 SYN 中携带数据(需协议支持)。


掌握三次握手原理后,可通过 Wireshark 抓包验证理论,并进一步分析网络延迟、连接重置(RST)等故障。

挥手

以下是 TCP 四次挥手(Four-way Handdrawal) 的详细解析,这是 TCP 连接终止的标准过程,确保双方数据完整传输并安全释放资源:


四次挥手流程

第一步:主动关闭方发送 FIN(终止请求)

  • 报文内容

    • 标志位:FIN=1(请求终止连接)

    • 序列号(Sequence Number):seq=u(当前已传输数据的最后一个字节序号 +1)

  • 主动方状态:从 ESTABLISHED 变为 FIN_WAIT_1

  • 作用:通知对方“我已无数据发送,请求关闭连接”(但仍可接收数据)。

第二步:被动关闭方回复 ACK(确认终止请求)

  • 报文内容

    • 标志位:ACK=1

    • 确认号(Acknowledgment Number):ack=u+1(确认 FIN 报文)

    • 序列号:seq=v(被动方当前数据序号)

  • 被动方状态:从 ESTABLISHED 变为 CLOSE_WAIT

  • 作用

    1. 确认收到 FIN 请求(ack=u+1

    2. 被动方可能仍有数据待发送(此时进入半关闭状态,只能发送不能接收)。

第三步:被动关闭方发送 FIN(最终关闭请求)

  • 报文内容

    • 标志位:FIN=1 + ACK=1

    • 序列号:seq=w(若第二步后被动方未发送新数据,则 w=v

    • 确认号:ack=u+1(与第二步一致)

  • 被动方状态:从 CLOSE_WAIT 变为 LAST_ACK

  • 触发条件:被动方数据全部发送完成后,主动发起 FIN 请求。

第四步:主动关闭方回复 ACK(最终确认)

  • 报文内容

    • 标志位:ACK=1

    • 序列号:seq=u+1(第一步 FIN 报文的序列号 +1)

    • 确认号:ack=w+1(确认被动方的 FIN 报文)

  • 主动方状态:从 FIN_WAIT_2 进入 TIME_WAIT(等待 2MSL 后关闭)

  • 作用

    1. 确保被动方收到最终 ACK(若丢失,被动方会重传 FIN)

    2. 等待处理网络中残留的旧报文(防止干扰新连接)。


关键机制解析

  1. 为什么需要四次挥手?

    • TCP 是全双工协议,双方需独立关闭各自的发送通道

      • 主动方发 FIN 表示“我不再发送数据”

      • 被动方发 FIN 表示“我也停止发送数据”

    • ACK 和 FIN 不能合并发送(被动方可能需处理遗留数据)。

  2. TIME_WAIT 状态的意义

    • 等待时间:2MSL(Maximum Segment Lifetime,报文最大生存时间,通常 60~120秒)

    • 核心作用

      • 确保最后一个 ACK 到达被动方(若丢失,被动方会重传 FIN)

      • 清除网络中滞留的旧报文(避免与新连接冲突)。

  3. 半关闭状态(Half-Close)

    • 在第二步后,被动方处于 CLOSE_WAIT 状态,仍可向主动方发送数据。

    • 典型场景:服务器通知客户端“数据已传完,准备关闭”。


抓包示例(Wireshark视角)

No.  Time        Source          Destination     Protocol Info
1    0.000000    Client_IP       Server_IP       TCP      FIN, ACK (seq=1000, ack=5000)
2    0.000042    Server_IP       Client_IP       TCP      ACK (seq=5000, ack=1001)
3    5.000120    Server_IP       Client_IP       TCP      FIN, ACK (seq=5000, ack=1001)
4    5.000150    Client_IP       Server_IP       TCP      ACK (seq=1001, ack=5001)
  • 观察要点

    • 前两次交互关闭主动方通道,后两次关闭被动方通道。

    • 序列号和确认号的递增逻辑(ack=seq+1)。

    • 时间戳差异(第三步可能有延迟,因被动方需处理数据)。


常见问题与故障场景

  1. 挥手异常情况

    • FIN 丢失:主动方重传 FIN(超时机制)。

    • LAST_ACK 状态卡死:若第四步 ACK 丢失,被动方持续重传 FIN。

    • 大量 TIME_WAIT 连接:高频短连接导致端口耗尽(优化:调整 SO_REUSEADDR 参数)。

  2. 为什么有时看到三次挥手?

    • 被动方的 ACK 和 FIN 可能合并发送(当被动方无数据待发时),但严格遵循 TCP 标准应为四次。

  3. 恶意 FIN 攻击

    • 攻击者伪造 FIN 报文强制关闭连接。

    • 防御:校验 SEQ/ACK 号合法性,或启用 TCP 身份验证(如 TCP-AO)。

💡注意:很多人会参考网上的博客去优化服务器参数,但请慎用net.ipv4.tcp_tw_recycle = 1,可能导致 NAT 问题。

问题现象

可能原因

排查方法

仅有SYN无响应

防火墙拦截/服务未启动

检查目标端口netstat -tulpn

FIN后长时间无ACK

应用层未释放连接

跟踪应用close()调用

出现多个FIN包

TCP连接复用

检查HTTP Keep-Alive设置

RST替代FIN

应用异常终止

结合程序日志分析


扩展思考

  • 同时关闭(Simultaneous Close):双方同时发送 FIN,进入 CLOSING 状态,最终通过 ACK 确认。

  • RST 报文强制终止:通过 RST=1 直接重置连接(不经历四次挥手,用于异常场景)。


掌握四次挥手机制后,可有效诊断以下问题:

  • 服务器出现大量 CLOSE_WAIT 连接(通常因应用未正确调用 close()

  • 客户端 TIME_WAIT 积累导致无法建立新连接

  • 防火墙误杀 FIN/ACK 报文导致连接无法正常关闭