TCP(传输控制协议)作为互联网的核心协议之一,其连接管理机制 —— 三次握手和四次挥手 —— 是确保数据可靠传输的关键。本文将结合理论与 Wireshark 抓包实践,让我们看看TCP的三次握手到底是什么。

TCP 三次握手

1. 握手过程详解

  • 第一次握手(SYN)
    客户端向服务器发送一个带有SYN=1标志的报文段,表示请求建立连接。此时客户端进入SYN_SENT状态。报文中包含一个随机生成的初始序列号(ISN),例如Seq=1926459878。该序列号用于后续数据传输的顺序标识。

  • 第二次握手(SYN+ACK)
    服务器收到请求后,回复一个SYN=1ACK=1的报文段。其中,ACK=1表示确认客户端的 SYN 请求,确认号Ack=1926459879(即客户端 ISN+1),同时服务器也会生成自己的初始序列号Seq=980795485。此时服务器进入SYN_RECEIVED状态。

  • 第三次握手(ACK)
    客户端验证确认号无误后,发送ACK=1的确认报文,确认号Ack=980795486(服务器 ISN+1),序列号为客户端 ISN+1(Seq=1926459879)。至此,双方进入ESTABLISHED状态,连接建立完成。

2. 核心设计逻辑

  • 防止重复连接:通过随机生成的 ISN 避免历史残留报文干扰新连接。

  • 双向确认:三次握手确保双方都能确认对方的发送和接收能力。若采用两次握手,服务器无法确认客户端是否收到 SYN+ACK,可能导致资源浪费。

TCP 四次挥手:连接终止的优雅告别

1. 挥手过程详解

  • 第一次挥手(FIN)
    客户端发送FIN=1的报文段,表示不再发送数据,进入FIN_WAIT_1状态。报文中的序列号Seq=1392(假设为当前数据的最后一个字节序号)。

  • 第二次挥手(ACK)
    服务器回复ACK=1确认收到 FIN,确认号Ack=1393(客户端 Seq+1),此时服务器进入CLOSE_WAIT状态。客户端收到 ACK 后进入FIN_WAIT_2状态。

  • 第三次挥手(FIN)
    服务器处理完剩余数据后,发送FIN=1的报文段,序列号Seq=607(假设为服务器当前数据的最后一个字节序号),确认号仍为Ack=1393。服务器进入LAST_ACK状态。

  • 第四次挥手(ACK)
    客户端收到 FIN 后,回复ACK=1确认,确认号Ack=608(服务器 Seq+1),序列号为Seq=1393。客户端进入TIME_WAIT状态,等待 2 倍报文最大生存时间(2MSL)后彻底关闭连接。

2. 为何需要四次挥手?

TCP 是全双工协议,每个方向需单独关闭。服务器在收到 FIN 后可能仍有数据待发送,因此需先回复 ACK 确认,再单独发送 FIN 关闭己方连接。若合并为三次挥手,可能导致数据丢失。

WireShark抓包

本文使用Navicat 去连接mysql数据库,使用Wireshark来查看抓包对应的报文。

首先打开 Wireshark,由于我的计算机使用以太网连接,因此在界面中双击 “以太网” 接口,即可开始捕获该接口上的所有数据包。

进入以后,在过滤器这里我们过滤mysql服务器的ip,ip.addr == 192.168.18.10 防止抓包太多,影响抓包分析。

然后我们可以用navicat 打开对应的mysql连接即可。然后我们就可以看到WireShark 中抓到了与mysql服务器192.168.18.10通信的数据包。

Wireshark 的抓包记录中,开头的三个报文清晰呈现了 TCP 三次握手的交互过程:首先,客户端(192.168.18.136)向服务器(192.168.18.10)发送了一个带有 [SYN] 标志的连接请求报文;服务器收到后,随即返回带有 [SYN,ACK] 标志的应答报文,既确认了客户端的请求,也同步发起了自身的连接序列;最后,客户端再以 [ACK] 报文回应,完成对服务器请求的确认。至此,抓包记录中完整展现了三次握手的闭环,TCP 连接正式建立。

Wireshark在此也清晰地为我们呈现了基于OSI七层网络模型的分层数据包结构,这里从数据链路层到传输层的每一层封装细节都被完整拆解,传输层数据(绿色)包含端口号等核心字段,这些数据会先传递给网络层;网络层(蓝色)会在其头部封装网络层信息,比如源 IP 地址、目的 IP 地址等;随后,封装后的数据包被交由数据链路层,数据链路层会进一步添加自身的头部信息(红色),例如源 MAC 地址、目的 MAC 地址;最终,完成层层封装的数据包被传递到物理层,由物理层转换为电信号或光信号进行传输。

展开TCP层的报文详情,我们可以清晰看到客户端发起第一次握手(SYN报文)时携带的信息:源端口号为56665、目的端口号为3306,序列号(Seq Number)为0、确认号(ACK Number)为0,SYN标志位被置为1,同时还包含了滑动窗口(Window)的大小信息。

文章作者: Z
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 微博客
运维 工具 计算机网络 基础
喜欢就支持一下吧