• 让你真实的看见 TCP 三次握手和四次挥手到底是什么样!


    前言

    TCP 建立连接是三次握手,而断开连接是四次挥手。

    但事实上从你打开这篇文章,到关掉这篇文章,你是看不见这个过程的。

    那 TCP 建立连接和断开连接的过程是不是真的如大多数文章所描绘的一样?

    带着这些疑问,那就不如真正去实战看一下。

    为了能“看见”TCP,我们需要借助 Wireshark 分析网络的利器。

    Wireshark 是 Windows 最常用的网络抓包和分析工具,称得上手好剑大利器把我们对数据包一目了然。(也是分析网络性能必不可少的利器)

    如果是在 Linux 上网络抓包,那可以使用 tcpdump。

    (分析网络的工具还有很多,但是工具只是手段,重要的是能实现目的)

    ————《用 Wireshark 让你看见 TCP 到底是什么样!》

    看得见的 TCP 的三次握手过程是什么样?

    如下图模型所示, TCP 建立连接过程三次握手是这样。

    Wireshark 中我们对请求网址后,可以使用表达式,筛选出网址源地址目标地址对应的请求信息。

    1. ip.dst == xxx.xxx.xxx.xxx or ip.src == xxx.xxx.xxx.xxx
    2. 复制代码

    如下图所示,筛选后如下,就可以清楚的看到 TCP 三次握手的信息。

    通过直接看标志位来看三次握手的数据包,第一个数据包标志位 SYN 是第一次握手;第二个数据包标志位 SYN,ACK 是第二次握手;第三个数据包标志位 ACK 是第三次握手。

    注意:如果你用Wireshark抓包程序看3次握手,你会发现SeqNum总是为0,是因为 Wireshark为了显示更友好,使用了Relative SeqNum——相对序号,你只要在右键菜单中的protocol preference 中取消掉就可以看到“Absolute SeqNum”了)

    第一次握手

    A主机发送一个请求的数据包,并将SYN (建立连接时的同步信号)置为1seq置为 0 ,表示A主机请求建立连接。

    我们可以再通过TCP 三次握手确认的信息图示,来看A主机和B主机在三次握手请求接收的能力。

    A主机向B主机第一次请求时,所能确认的事情,只有在B主机知道,B主机一旦确认接收到了对方的请求,那么也就确认了自己具备接收和对方请求的能力。如下图所示。

    第二次握手

    B主机收到A主机发过来的请求数据包后,通过SYN得知是一个建立连接的请求,于是响应一个确认数据包,并将 SYNACK (对收到的数据进行确认,即表示响应) 状态都置为 1

    并且将确认序列号 ACK 设置为序号 seq = 0 + 1 = 1,表示B主机收到A主机发过来的SYN。如下图示。

    而在到了第二次握手后,A主机就可以确认自己和对方的请求的能力,但B主机还有两个信息无法确认,自己的请求和对方的请求。

    第三次握手

    A 收到B的响应包后需确认序号ACK是否正确,如果正确,A主机会再向B主机发送一个数据包,数据包中将SYN置为 0ACK 置为 1,并将确认序列号设置为 y+1 = 1,表示收到了来自 BSYN。于是,AB两端就TCP建立起三次握手的连接。

    如下图可以直观看到在第三次握手后,B主机就能确认自己的请求和对方的接收都是正常的。

    为什么需要三次握手?两次可以吗?

    这是一个好工程师,会提出想要优化的好问题。

    这要说到在IP数据包中历史存在的问题,IP数据包在发送时,为了防止出现数据包不断在网络上永不终止地循环和收发,所以在数据报文中会加上数据包报文的生存时间,也就是 TTL(time to live) 来解决这个问题。

    但是在TCP中,网络报文的生存时间往往会超过TCP请求超时的时间,如果两次握手来创建连接,传输数据并释放连接后,一旦第一个超时的连接通过重试机制后,请求才到达 B 主机的话,那么 B 主机会以为是 A 创建新连接的请求,然后确认同意创建连接。就会直接导致A主机丢弃了 B 原来的确认数据,最后只有 B 主机方面创建连接完毕。

    所以两次握手会请求超时导致的脏连接,而三次握手可以防止超时,同时保证信息对等

    看得见的 TCP 的四次挥手的过程是什么样?

    接着TCP如果断开连接, Wireshark 自然也不会放过,可以看到如下图所示。

    (会发现对应上图模型是不是就很具体了)

    第一次挥手

    A主机想断开连接,则在数据发送完毕后,传递FIN(表示关闭连接)信号给B主机。FINACK置为1,序号seq=X=4335,确认序号ACK=Z=10615.

    第二次挥手

    B 主机收到FIN后,则响应 ACK,告诉 A 主机可以断开,seq序号=确认序号ack=10615;并将ACK=1

    第三次挥手

    B 主机做好连接关闭前的准备工作后,发再次发送FINA主机,此时B主机也进入半关闭状态。因为A主机可能还有没发完的数据,所以需要等B主机发送完数据会发送一个FIN + ACK进行最后的确认。

    第三次挥手的序号确认序号不需要改变,只是多了一个FIN来确认结束。

    第四次挥手

    A主机收到B主机的FIN后,会发送ACK来确认后会进入TIME-WAIT状态,经过2MSL(Maximum Segment Lifetime)后,没有收到B主机传来的报文,则确定B 主机已经收到A主机最后发送的ACK 指令,此时TCP连接正式释放。

    最后

    好了,这些天就到这里了。但TCP还有很多东西,除了各种实现可靠的机制和治理交通似的算法,而且还有很多优化和变种。

    想想到如今车一旦多起来,交通还是面临很多问题,你就知道TCP好像没那么简单了。

    所以TCP的文章也相当多,但是不是真的是这样?就不如实际去看看。

    计算机本就是一个实践性很强的的学科啊。

  • 相关阅读:
    训练一个图像分类器demo in PyTorch【学习笔记】
    你应该知道的JavaScript操作对象方法总结
    Hippy - 值得关注的免费开源跨端开发框架,由腾讯出品,支持将 JS 代码发布到安卓 / iOS / web
    ABP-VNext 用户权限管理系统实战06---实体的创建标准及迁移
    jmeter-函数助手,关联数据,CSV文件读取
    MySQL主从复制与读写分离
    【计算机毕业设计】java ssm网上宠物商店系统
    【动态规划】求解编辑距离问题
    基于Java咖啡商品管理系统设计实现(源码+lw+部署文档+讲解等)
    go 中解析JSON的三种姿势
  • 原文地址:https://blog.csdn.net/BASK2311/article/details/128145295