八股文中TCP三次握手怎么具象理解?

内容开始前,我们摘抄TCP三次握手的内容,抢救一下死去的回忆

  • 一次握手 :客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务端的确认;
  • 二次握手 :服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 --> 客户端,然后服务端进入 SYN_RECV 状态;
  • 三次握手 :客户端发送带有 ACK(ACK=y+1) 标志的数据包 --> 服务端,然后客户端和服务端都进入ESTABLISHED 状态,完成 TCP 三次握手。

当建立了 3 次握手之后,客户端和服务端就可以传输数据啦!

我们知其然了,接下来,我们看看如何知其所以然。

从一个Get请求来探索

我们先从一个最简单的http请求开始说起。我们找一个网络的静态文件,比如

bash 复制代码
http://h5-sdk.tinytool.top/public/index.css

我们使用浏览器新开一个标签页,请求一下

这就是我们平时的文件请求了,我们可以看到请求的入参,返回的结果。很方便,但浏览器NetWork选项卡是不能直接看到TCP的连接信息的,我们想继续深入,我们得借助一个网卡抓包工具:WireShark。

具体的下载地址和使用方法请参考这个博客:wireshark抓包新手使用教程,这里不额外展开。

Wireshark抓包

我们安装完wireshark后,和一般应用打开,选择我们的使用的对外网卡,我这里是一个wifixxx的标识,选择之后,我们就能看到一堆数据,太多数据了,我们无从下手,得通过方法先筛选一下。

我们可以看到上面是一个域名请求,wireshark的过滤器一般是通过ip来进行过滤的,我们先取一下这个域名解析一下

python 复制代码
ping h5-sdk.tinytool.top
PING h5-sdk.tinytool.top (43.139.59.79): 56 data bytes
64 bytes from 43.139.59.79: icmp_seq=0 ttl=55 time=10.521 ms
64 bytes from 43.139.59.79: icmp_seq=1 ttl=55 time=15.268 ms
64 bytes from 43.139.59.79: icmp_seq=2 ttl=55 time=8.404 ms

我们得到了ip为: 43.139.59.79 的服务器地址,我们wireshark过滤条件设置为: ip.addr == 43.139.59.79, 然后我们就可以抓包了。

在网页执行一次刷新,我们就可以看到wireshark的抓包界面有具体的信息了。

我们可以看到,在HTTP请求前,存在三个TCP的连接信息,在我框住红色的部分的右边,有相关SYN, SYN+ACK, ACK三条对应的信息,可以很容易和TCP的三次握手对应起来。

翻译一下:

  • 172.16.80.14 这个地址是第一个包的原地址(Source), 对应我们握手流程的客户端

  • 43.139.59.79 这个地址是第一个包的目标地址(Destination), 对应我们握手流程的服务端

  • SYN: SYNchronize(同步)

  • SYN+ACK: SYNchronize-Acknowledgement(同步-确认)

  • ACK: ACKnowledege(确认)

继续深入分析

好了,我们已经知道怎么去抓三次握手过程中的数据包了,我们拿上面引用内的第一个握手流程继续理解

一次握手 :客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务端的确认;

Okk, 我们继续,第一条数据我们看到,172.16.80.14 先给 43.139.59.79 发了一个TCP的包,这个包内部会携带SYN标识,代表他是握手的第一步。那么他如何携带的呢?我们得先了解一下TCP的报文结构,参考TCP规范文档 RFC793 我们了解到TCP的报文头部结构

css 复制代码
  0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

报文的来源:我们都知道数据在底层是以二进制进行传输的,那么一个数据包假如需要携带多个信息的话,应该怎么做呢?很明显,我们需要制定一个规则,让他们按照特定的规则(比如顺序)排列起来,这样通信双方,只要事先只要这个规则,就可以按照这个规则,去将数据隔离开来,翻译一下,就得到了想要的数据,nice~

我们看到上方的的TCP报文有一个SYN的加粗,当报文的这个标志为1的时候,他就代表他属于一个SYN包,用来做握手使用的。Sequence Number代表包的序号。每个数据包都有这个序号。好了我们要数据来实际分析了,我们点击第一条握手信息,在下方会出现好几个数据分析的区域。我们对他先有一个初步的认识

这里的红字是根据网络七层协议标注的他们对应的数据,他们在这里的关系是一层包裹一层,我们只需要关注最后一层数据就行,因为TCP是传输层协议,他的报文信息在这里就可以进行分析,我们对他进行展开。

这里看到的内容比较多,其实和上面的报文基本一一对应,wireshark贴心帮我们标注了他们了的对应的信息,这里我们只需要关注Sequence 和Syn这两个值就可以。 他的SYN标志设置了为1,和我们的理解差不多,这里的Seq的值在这里是2876456852, 按照上方的说法

二次握手 :服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 --> 客户端,然后服务端进入 SYN_RECV 状态;

当二次握手,ACK = x + 1, ACK的值,应该是 2876456852 + 1 也就是 2876456853才对。我们验证一下,我们点击一下第二条握手信息看看数据

可以,所料不错。那么第三次握手的信息也应该如此,数据报文的Acknowledgment报文应该是当前报文的Seq + 1.我们看看

三次握手 :客户端发送带有 ACK(ACK=y+1) 标志的数据包 --> 服务端,然后客户端和服务端都进入ESTABLISHED 状态,完成 TCP 三次握手。

这里的y是第二个握手的Seq的值,这样我们ACK = y + 1 应该为3320095631 + 1 = 3320095632, 我们看一下是不是

这样,我们就了解这个握手协议在数据层是怎么联系起来的了。

网络异常情况

我们可以通过网上资料查询到TCP握手异常情况机制

他在wireshark中是怎么样的呢?我们简单模拟一下第一种场景,我们通过终端简单模拟一下请求一个ipv4地址

bash 复制代码
curl 185.26.48.56
# curl: (28) Failed to connect to 185.26.48.56 port 80 after 75002 ms: Couldn't connect to server

通过wireshark抓包我们可以看到

我们通过wireshark可以看到抓包数据,我们客户端在一直超时发送SYN包, 符合理论的结果。

希望对你理解有所帮助

相关推荐
艾恩小灰灰13 分钟前
CSS中的`transform-style`属性:3D变换的秘密武器
前端·css·3d·css3·html5·web开发·transform-style
Captaincc14 分钟前
AI coding的隐藏王者,悄悄融了2亿美金
前端·后端·ai编程
天天扭码18 分钟前
一分钟解决一道算法题——矩阵置零
前端·算法·面试
盖世英雄酱5813624 分钟前
同事说缓存都用redis啊,数据不会丢失!真的吗?
redis·后端·面试
抹茶san30 分钟前
el-tabs频繁切换tab引发的数据渲染混淆
前端·vue.js·element
Captaincc34 分钟前
关于MCP最值得看的一篇:MCP创造者聊MCP的起源、架构优势和未来
前端·mcp
小小小小宇38 分钟前
记录老项目Vue 2使用VueUse
前端
vvilkim38 分钟前
React Server Components 深度解析:下一代 React 渲染模式
前端·react.js·前端框架
HBR666_1 小时前
vue3 excel文件导入
前端·excel
天天扭码1 小时前
偶遇天才算法题 | 拼劲全力,无法战胜 😓
前端·算法·面试