输入URL到显示页面的过程

339 阅读5分钟

前言:本篇文章会从个人理解和学习到的知识出发(极客时间小林Coding),详细介绍我眼中的,输入URL到显示页面的过程。如果有错误,可以在评论区积极指正!感谢您的点赞和评论~

判断URL是否合法

输入url按下回车之后,浏览器首先会判断该URL是否合法,如果不合法会用浏览器搜索引擎进行搜索,合法的话进入下一步。

在本地强缓存中查找

如果URL是合法的,会先在本地强缓存中查找对应资源,如果找到了对应的缓存资源,并且这个缓存的max-age没有过期,就命中该资源,返回200状态码和资源。否则就进入下一步。

进行DNS解析

没有命中强缓存,所以要进行DNS解析,获取ip并请求资源。

首先介绍一下域名的层级关系:

  • 根DNS服务器
  • 顶级DNS服务器(com)
  • 权威DNS服务器(baidu.com)

image.png

假设我们现在要访问www.baidu.com,那么流程是什么样的呢?

  • 客户端首先会发出一个DNS请求给本地DNS服务器

  • 本地DNS服务器收到客户端的请求后

    • 如果在缓存中能找到对应的域名,就直接返回域名对应的IP地址
    • 如果没有,本地DNS就会访问根域名服务器(根域名服务器是最高层次,不直接用于域名解析,但能指明道路
  • 根DNS收到请求后,发现是.com,返回.com顶级域名服务器地址

  • 本地DNS收到顶级域名服务器地址后,继续发送请求给顶级DNS

  • 顶级服务器返回www.baidu.com的权威DNS服务器地址

  • 本地DNS收到权威DNS服务器的地址之后,发送请求给权威DNS服务器,随之获取到对应的IP

  • 本地DNS再将IP地址返回给客户端,客户端和目标建立连接

TCP三次握手建立连接

获取到对应服务器的ip后,要经过三次握手建立tcp连接。

  • 客户端生成Client_num并且存入tcp首部的序号字段,标记SYN为1发送给服务器。
  • 服务器收到Client_num之后+1并保存在确认号字段中,并且自己也生成一个随机数Server_num,存入序号字段,标记SYN和ACK为1,发送给客户端。
  • 客户端收到Server_num之后+1并保存在确认号字段中,并且标记ACK为1,发送给服务器。

至此,三次握手结束,TCP连接建立。

image.png

开启协商缓存请求资源

协商缓存分为ETag和Last Modified两种

Etag是文件资源对应的唯一字符串,比较精准。

LastModified是文件资源对应上一次的修改时间

  • 首先是判断请求头中是否携带了If-None-Match字段,如果携带了,会跟服务器对应资源的Etag值进行对比,如果是相同的,就说明命中了协商缓存,返回304状态码,让浏览器在本地获取资源。

  • 其次是判断请求头中是否携带了If-Modified-Since字段,如果携带了,会跟服务器对应资源的Last-Modifed值进行对比,如果是相同的,就说明命中了协商缓存,返回304状态码,让浏览器在本地获取资源。否则就响应对应的资源,返回200状态码

开启渲染进程,解析成DOM树

请求到HTML资源之后,浏览器是无法直接识别HTMl字节流的。所以会开启渲染进程,与网络进程之间建立管道,网络进程通过管道将HTML字节流交给渲染进程。渲染进程中将HTMl字节流转成浏览器能认识的DOM树结构。

解析css

浏览器默认也是不认识css样式的,所以要将css转成浏览器能认识的styleSheets结构(可以通过document.styleSheets查看)。

image.png

生成布局树(重排的过程)

我们有了dom树和每个dom结点对应的css样式规则之后,要计算每个dom元素的css样式,以及布局位置,生成布局树。

生成分层树(重排的过程)

网页其实是由一个个图层构成的(使用position或者z-index等属性可以改变盒子的层级),所以还要将布局树转成分层树。

image.png

生成绘制列表 (重绘的过程)

生成每个图层的"绘制列表",其实就是一个个绘制指令(指明如何一步步渲染),生成完绘制列表之后,会交给合成线程进行处理。

image.png

image.png

图层转图块,光栅化

合成线程会将每个图层生成一个个的图块。而浏览器视口大小是有限的,所以会优先处理距离视口更近的图块,将他们经过光栅化转成位图。

image.png

发送绘制图块指令,渲染页面

在合成线程中,所有的图块都光栅化完毕之后,会发送图块绘制指令给浏览器进程,浏览器进程会根据绘制指令来渲染出对应的页面。

TCP四次挥手,断开连接

image.png

  • 客户端打算关闭连接,发送一个FIN报文,客户端会进入FIN_WAIT状态
  • 服务器端受到之后,发送ACK报文,处理目前还在处理的数据,此时服务器端进入CLOSE_WAIT状态,客户端进入FIN_WAIT2状态
  • 服务器处理完数据后,发送FIN报文,进入LAST_ACK状态
  • 客户端受到FIN报文后,发送ACK报文,并且在2MSL之后进入关闭状态,服务器受到ACK报文之后也会进入关闭状态

这里等待2MSL(Max Segment Lifetime,最大报文存活时间)是为了确保服务器接收到了客户端最后发出的ACK(因为如果没收到的话,服务器会重发FIN包,那么两个包的最大存活时间就是2MSL)。如果2MSL内没有收到服务器重发的报文,那么就说明不需要重传,断开连接。