HTTP:抓包分析[输入网址到响应]的过程

两个场景

使用IP地址访问Web服务器

操作

实验环境待搭建中,我们使用IP地址访问web服务器

  • 首先我们运行 www 目录下的“start”批处理程序,启动本机的 OpenResty 服务器,启动后可以用“list”批处理确认服务是否正常运行。
  • 然后我们打开 Wireshark,选择“HTTP TCP port(80)”过滤器,再鼠标双击“Npcap loopback Adapter”,开始抓取本机 127.0.0.1 地址上的网络数据。
  • 第三步,在 Chrome 浏览器的地址栏里输入“http://127.0.0.1/”,再按下回车键,等欢迎页面显示出来后 Wireshark 里就会有捕获的数据包,如下图所示。
    HTTP:抓包分析[输入网址到响应]的过程_第1张图片
    如果你还没有搭好实验环境,或者捕获与本文里的不一致也没关系。我把这次捕获的数据存
    成了 pcap 包,文件名是“08-1”,放到了GitHub 上,你可以下载到本地后再用
    Wireshark 打开,完全精确“重放”刚才的 HTTP 传输过程。

分析

HTTP协议是运行在TCP/IP上的,依靠TCP/IP协议来实现数据的可靠传输,所以浏览器要用HTTP协议发送数据,首先要做的就是建立TCP连接

因为我们在地址栏中直接输入了IP地址“127.0.0.1”,而Web服务器的默认端口是80,所以浏览器要依照TCP协议的规范,使用“三次握手”建立与Web服务端的连接。

对于到wireshark里面,就是最开始的三个包: 浏览器使用的端口是52085,服务器使用的端口是80,经过SYN,SYN/ACK、ACK的三个包之后,浏览器与服务器的TCP连接就建立起来了
在这里插入图片描述
问题:为什么又进行了一次tcp连接呢?

  • 因为HTTP/1连接传输效率低,所以浏览器一般都会同一个域名发起多个连接提高效率
  • 并发多个连接,可以提高数据传输效率

有了可靠的TCP连接通道之后,HTTP协议就可以工作了。

于是,浏览器就按照HTTP协议规定的格式,通过TCP发送了一个“GET HTTP/1.1”请求报文
HTTP:抓包分析[输入网址到响应]的过程_第2张图片
随后,web服务器回复了这个包,在TCP协议层确认:“刚才的报文我已经收到了”,不过这个TCP包HTTP协议是看不见的
HTTP:抓包分析[输入网址到响应]的过程_第3张图片
web服务器收到报文后再内部就要处理这个请求。同样也是依据HTTP协议的规定,解析报文,看看浏览器发送这个请求时想要干什么。

随后,它会知道原来是要求获取根目录下的默认文件。于是,它就会从磁盘上把那个文件全部读取出来,在拼成符合HTTP报文的格式,发回去。即““HTTP/1.1 200 OK”
HTTP:抓包分析[输入网址到响应]的过程_第4张图片
同样,浏览器也要给服务器发送一个TCP的ACK确认:“你的响应报文收到了,多谢”
HTTP:抓包分析[输入网址到响应]的过程_第5张图片
随后,浏览器就会解析收到的响应报文。它会发现服务器传回来的是个HTML文件,因此,它就会调用排版引擎,JS引擎处理,然后在浏览器窗口展示出欢迎界面。

HTTP:抓包分析[输入网址到响应]的过程_第6张图片

这之后还有两个来回,共四个包,重复了相同的步骤。这是浏览器自动请求了作为网站图标
的“favicon.ico”文件,与我们输入的网址无关。但因为我们的实验环境没有这个文件,
所以服务器在硬盘上找不到,返回了一个“404 Not Found”。
HTTP:抓包分析[输入网址到响应]的过程_第7张图片
至此,“键入网址再按下回车”的全过程就结束了

总的交互如下:

HTTP:抓包分析[输入网址到响应]的过程_第8张图片
图中TCP关闭连接的“四次挥手”在抓包中没有出现,这是因为HTTP/1.1长连接特性,默认不会立即关闭连接。

再简要叙述一下这次最简单的浏览器 HTTP 请求过程:

  • 浏览器从地址栏的输入中获得服务器的 IP 地址和端口号;
  • 浏览器用 TCP 的三次握手与服务器建立连接;
  • 浏览器向服务器发送拼好的报文;
  • 服务器收到报文后处理请求,同样拼好报文再发给浏览器;
  • 浏览器解析报文,渲染输出页面。

  • 因为chrome浏览器会缓存之前访问过的网站,所以当你再次访问“127.0.0.1”的时候它可能会直接从本地缓存而不是服务器获取数据,这样就无法用wireshark捕获网络流量,解决方法是在chrome的开发者工具清除缓存
  • 现代浏览器通常都会自动而且秘密的发送favicon.ico请求

使用域名访问 Web 服务器

刚才我们是在浏览器地址里直接输入IP地址,但绝大多数情况下,我们是不知道服务器的IP地址值的,使用的是域名。那么改用域名后这个过程会有什么不同吗?

还是实际动手试一下吧,把地址栏的输入改成“http://www.chrono.com”,重复
Wireshark 抓包过程,你会发现,好像没有什么不同,浏览器上同样显示出了欢迎界面,抓到的包也同样是 11 个:先是三次握手,然后是两次 HTTP 传输。
HTTP:抓包分析[输入网址到响应]的过程_第9张图片

这里就出现了一个问题:浏览器是如何从网址里面知道“www.chrono.com”的IP地址就是“127.0.0.1”的呢?

浏览器看到网址里的“www.chrono.com”,发现它不是数字形式的IP地址,那就肯定是域名了,于是就会发起域名解析动作,通过访问一系列的域名解析服务器,视图把这个域名翻译成TCP/IP协议里的IP地址。

不过因为域名解析的全过程实在是太复杂了,如果每个域名都要大费周折的去网上查一下,那么我们上网肯定非常慢。

于是,在域名解析的过程中就会有多级的缓存,浏览器先看一下自己的缓存里有没有,如果没有就向操作系统的缓存要,还没有就检测本机域名解析地址hosts,也就是上一讲中我们修改的“C:\WINDOWS\system32\drivers\etc\hosts”。

刚好,里面有一行映射关系“127.0.0.1 www.chrono.com”,于是浏览器就知道了域名对应的 IP 地址,就可以愉快地建立 TCP 连接发送 HTTP 请求了。

即:使用域名访问web服务器和使用IP访问服务器的不同在于:域名时浏览器需要DNS解析

HTTP:抓包分析[输入网址到响应]的过程_第10张图片

总结

根据上面两个场景,对于HTTP协议的工作流程:

  • 第一个场景:
    • 只有两个角色,浏览器、服务器
    • 浏览器可以直接用IP地址找到服务器,两者直接建立TCP连接后发送HTTP报文通信
  • 第二个场景:
    • 三个角色:浏览器、DNS、服务器
    • 浏览器不知道服务器的IP地址,所以必须要借助DNS的域名解析功能得到服务器的IP地址值,然后才能与服务器通信

总结

  • HTTP协议基于底层的TCP/IP协议,所以必须要用IP地址建立连接
  • 如果不知道IP地址,就要用DNS协议去解析得到IP地址,否则就会连接失败
  • 建立TCP连接之后会顺序收发数据,请求发和应答方都必须依据HTTP规范构建和解析报文
  • 为了减少响应时间,整个过程中的每一个环境都有缓存
  • 在上面,我们使用wireshark抓包,弄清楚了HTTP协议的工作流程,也就是“请求-应答”模式
  • 可以看到,HTTP是由底层的TCP/IP协议负责底层的具体传输工作,单从这一点来看,所谓的“超文本传输协议”其实并不怎么管“传输”的事情,优点名不副实
  • 那么HTTP协议的核心部分是什么呢?
    • HTTP协议在规范文档中详细定义了报文的格式,规定了组成部分、解析规则,还有处理策略
    • 所以可以在TCP/IP层之上实现更灵活丰富的功能,比如连接管理、缓存管理、数据编码、内容协商等等

你可能感兴趣的:(网络,http,tcp/ip,前端)