通过Wireshark理解计算机网络

引言

转眼毕业已经两年半了(警觉),写代码的时候通过axios或者xhr发送一个请求,就能获取到对应的结果,然而一时半会儿也无法回忆起这背后所经历的过程。像一个黑盒、语法糖一样,甜得让人不安。

Wireshark基础

简介

Wireshark 是一个流行的、开源的网络协议分析器(也常被称为"抓包工具")。它用于捕获和分析计算机网络上的数据包。通过 Wireshark,网络管理员、安全专家和开发人员可以查看网络上的数据流,诊断网络问题,分析协议的实现情况,以及调查安全问题。

安装

下载地址

根据自己的系统版本选择对应的链接进行下载即可

我是Mac M2芯片,选择其中的 macOs Arm Disk Image

基本界面与功能介绍

安装完成后打开wireshark,他的基本界面如下:

点击蓝色的鲨鱼鳍即可开始抓包

之后鲨鱼鳍会变成绿色,并抓取经过电脑网卡的包

⚠️注意:Wireshark默认情况下不会捕获本地回环接口(Loopback Interface)上的数据包:即localhost

图中分为三个区域

区域 内容 功能
Packet List Pane(数据包列表) 显示捕获到的数据包,每个数据包包含编号,时间戳,源地址,目标地址,协议,长度,以及数据包信息
Packet Details Pane(数据包详细信息) 在数据包列表中选择指定数据包,在数据包详细信息中会显示数据包的所有详细信息内容
数据包的具体内容 显示对应的数据报文内容,支持多种编码解析

更多介绍可以看看这篇文章Wireshark的抓包和分析,看这篇就够了

如果抓包的过程中遇到了以下错误:

可以试试这篇文章的解决方案:Mac无法使用wireshark进行抓包,报错

OSI七层模型

开放系统互联(Open System Interconnect 简称OSI)模型,由国际标准化组织(ISO)于1980年代定义。该模型将网络协议的功能分为七个不同的层次,使得不同的网络功能和协议可以在适当的层次上进行设计和实施。

更加详细的内容见:详解 四层、五层、七层 计算机网络模型

curl请求过程

我们通过在控制台执行以下命令来阐述http请求与响应的整个过程

shell 复制代码
curl http://www.baidu.com

执行命令之前,我们先过滤http的内容,并点击蓝色的鲨鱼鳍,开始抓包:

接着执行以上命令,然后在面板上可以看到以下内容:

选中对应的内容,并右键Follow -> HTTP Stream

之后会有一个弹窗,展示整个http会话过程,红色部分为请求,蓝色部分为响应,我们可以将右下角的Show data as ASCII 改为Show data as UTF-8,以便正确展示中文内容

关闭弹窗之后,所显示的数据包列表即为整个请求过程,包含以下内容:

  1. 握手
  2. http请求
  3. http响应
  4. 挥手

数据包详细信息

其中每一个数据包都至少包含四层协议,图中显示了Get请求所包含的五层协议

IP报文与TCP报文

IP数据报格式

TCP数据报格式

传输过程

从上往下,每经过一层协议就会在数据包包头上面做点手脚,加点东西,传送到接收端,再层层解套出来。这个过程很像我们寄收快递的过程,我们先把快递(原始数据)送到快递站,快递员会给我们的快递贴上标签,包含了寄件人和收件人的信息。示意图如下:

握手过程

TCP建立连接的过程叫做握手,握手需要在客户端和服务器之间交换三个TCP报文段

对应上图中前三个数据包

为什么要三次握手?两次不行吗?

  • 为了确认双方的接收能力和发送能力都正常
  • 如果是用两次握手,则会出现下面这种情况:

如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。

简而言之:

  • 三次握手才可以阻止重复历史连接的初始化(主要原因)
  • 三次握手才可以同步双方的初始序列号
  • 三次握手才可以避免资源浪费

第一次握手

客户端向服务器发送了一个seq=0SYN=1的数据包,表示客户端需要与服务器建立连接,发送完成后进入SYN_SENT状态

第二次握手

服务器收到客户端发送的SYN=1的数据包之后,得知这是一个连接建立请求,于是回复了ack=0+1seq=0SYN=1的数据包,并进入SYN_RCVD状态

第三次握手

客户端回复服务器发送的SYN数据包,返回一个ack=0+1的确认数据包之后,双方建立连接进入ESTABLISHED状态

HTTP请求与响应

对应的数据包如图所示

请求报文

http请求由4部分构成:

  • 请求行
  • 请求头
  • 空行
  • 请求体

响应报文

http响应也由4部分构成:

  • 响应行
  • 响应头
  • 空行
  • 响应体

数据包格式与细节

这里就不赘述了,大家可以点开具体的报文查看,但需要注意以下两点:

  1. 基于https的数据包都是经过加密的,看不到原文内容
  2. Wireshark默认的解码格式为ASCII ,如果包含中文,则无法正确显示,需要使用UTF-8格式

挥手过程

数据传输结束之后,通信的双方都可以主动释放连接

对应以下四个数据包

同握手过程相似,只不过将SYN标识为改为了FIN,表示关闭连接请求ack确认序号为seq + 1。需要注意的是,最后一次挥手过后,需要等待2MSL的长,双方才会真正断开链接,这么做有以下目的:

  • 重传最后一个ack报文,确保对方可以收到。因为如果对方没有收到ack的话,会重传fin报文,处于time_wait状态的套接字会立即向对方重发ack报文。
  • 同时在这段时间内,该链接在对话期间于网际路由上产生的残留报文(因为路径过于崎岖,数据报文走的时间太长,重传的报文都收到了,原始报文还在路上)传过来时,都会被立即丢弃掉。4分钟的时间足以使得这些残留报文彻底消逝。不然当新的端口被重复利用时,这些残留报文可能会干扰新的链接。

为什么需要四次挥手?

因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,"你发的FIN报文我收到了"。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送,故需要四次挥手。

参考

相关推荐
帽儿山的枪手1 小时前
追踪网络流量就这么简单 | 进阶篇 | conntrack
linux·windows·网络协议
阿维的博客日记1 小时前
TCP和UDP区别
tcp/ip·udp·php
yqcoder1 小时前
7. TCP 和 UDP 的区别
网络·网络协议·http
wanhengidc1 小时前
UDP服务器的优缺点都包含哪些?
服务器·网络协议·udp
小猫会后空翻3 小时前
HTTPS与DNS
网络协议·http·https
hrrrrb4 小时前
【TCP/IP】14. 远程登录协议
网络·网络协议·tcp/ip
别枫了4 小时前
TCP的连接
服务器·网络·tcp/ip
小镇敲码人4 小时前
【实习篇】之Http头部字段之Disposition介绍
网络·网络协议·http
黎相思4 小时前
应用层协议HTTP
网络·网络协议·http
DoraBigHead7 小时前
第三章 · 数据链路层:打包大师,局域江湖
网络协议