本文已参与「新人创作礼」活动,一起开启掘金创作之路。详情
从url输入到页面打开实际上都要哪些过程解析呢?
- DNS域名解析
- 建立TCP连接
- 发送HTTP请求,服务器处理请求,返回相应结果
- 关闭TCP连接
- 浏览器渲染 过程流程图
合成URL
用户输入URL,浏览器会根据用户输入的信息判断是搜索还是网址。
如果是搜索内容,就将搜索内容+默认搜索引擎合成新的URL。
如果用户输入的内容符合URL规则,浏览器就会根据URL协议,在这段内容上家扫协议合成合法的URL。
1、DNS解析
DNS的域名查找,在客户端和浏览器,本地DNS之间的查询方式是递归查询;在本地DNS服务器与根域及其子域之间的查询方式是迭代查询;
- 在客户端输入 URL 后,会有一个递归查找的过程
- 从
浏览器缓存中查找->本地的hosts文件查找->找本地DNS解析器缓存查找->本地DNS服务器查找,这个过程中任何一步找到了都会结束查找流程。 - 如果本地DNS服务器无法查询到,则根据本地DNS服务器设置的转发器进行查询。
- 若未用转发模式,则迭代查找过程如下图:
【注】跟DNS/顶级/权威DNS服务器:
- 根 DNS 服务器 :返回顶级域 DNS 服务器的 IP 地址
- 顶级域 DNS 服务器:返回权威 DNS 服务器的 IP 地址
- 权威 DNS 服务器 :返回相应主机的 IP 地址
总体流程就是:
在查找过程中,有以下优化点:
- DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种:
浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。 - 在域名和 IP 的映射过程中,给了应用基于域名做负载均衡的机会,可以是简单的负载均衡,也可以根据地址和运营商做全局的负载均衡。
2、建立TCP连接
首先,判断是不是https的,如果是,则HTTPS其实是HTTP + SSL / TLS 两部分组成,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据
TCP建立连接时进行三次握手:
-
第一次握手:【建立连接。客户端发送连接请求报文段。】将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认。
-
第二次握手:【服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认】设置Acknowlegment Number为x+1(Sequence Number+1);同时,自己还要发生SYN请求信息,将SYN设置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发生给客户端,此时服务器进入SYN_RECV状态。
-
第三次握手:【客户端收到服务器的SYN+ACK报文段,向服务器发送ACK报文段。】然后将Acknowlegment Numbe设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务端都进入ESTABLISHED状态,完成TCP三次握手。
SSL握手过程
- 第一阶段 建立安全能力 包括协议版本 会话Id 密码构件 压缩方法和初始随机数
- 第二阶段 服务器发送证书 密钥交换数据和证书请求,最后发送请求-相应阶段的结束信号
- 第三阶段 如果有证书请求客户端发送此证书 之后客户端发送密钥交换数据 也可以发送证书验证消息
- 第四阶段 变更密码构件和结束握手协议
完成了之后,客户端和服务器端就可以开始传送数据
3、发送HTTP请求
发送HTTP请求,服务器处理请求,返回响应结果
TCP连接建立后,浏览器就可以利用
HTTP/HTTPS协议向服务器发送请求了。服务器接受到请求,就解析请求头,如果头部有缓存相关信息如if-none-match与if-modified-since,则验证缓存是否有效,若有效则返回状态码为304,若无效则重新返回资源,状态码为200
这里有发生的一个过程是HTTP缓存,可以查看缓存机制详解
4、关闭TCP连接
第一次挥手:主机1(可以是客户端也可以是服务器)设置Sequence Number和Acknowlegment Number,向主机2发送一个FIN报文段;此时主机1进入FIN_WAIT_1状态;【这表示主机1没有数据要发送主机2了。】
第二次挥手:主机2收到主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowlegment Number设置为Sequence Number+1;主机1进入FIN_WAIT_2状态。【主机2告诉主机1,我同意你的关闭请求】
第三次挥手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态。
第四次挥手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态。主机2收到ACK报文段后,关闭连接。此时主机1等待2MSL后依旧没收到回复,则证明连接已正常关闭,主机1也关闭连接。
5、浏览器渲染
渲染进程将HTML内容转化为能够读懂的DOM树结构。
渲染引擎将CSS样式表转化为浏览器可以理解的styleSheets。计算出DOM节点的样式。
创建布局树,并计算元素的布局信息。
对布局树进行分层,并生成分层树。
为每个图层生成绘制列表,并将其提交到合成线程。合成线程将图层分图块,并格栅化将图块转换成位图。
合成线程发送绘制图块命令给浏览器进程。浏览器进程根据指令生成页面,并显示到显示器上。
按照渲染的时间顺序,流水线可分为如下几个子阶段:构建 DOM 树、样式计算、布局阶段、分层、栅格化和显示。如图:
-
构建 DOM 树
渲染进程将 HTML 内容转换为能够读懂DOM 树结构,经历下面4个过程:
- 转码(Bytes -> Characters)—— 读取接收到的 HTML 二进制数据,按指定编码格式将字节转换为 HTML 字符串
- Tokens 化(Characters -> Tokens)—— 解析 HTML,将 HTML 字符串转换为结构清晰的 Tokens,每个 Token 都有特殊的含义同时有自己的一套规则
- 构建 Nodes(Tokens -> Nodes)—— 每个 Node 都添加特定的属性(或属性访问器),通过指针能够确定 Node 的父、子、兄弟关系和所属 treeScope(例如:iframe 的 treeScope 与外层页面的 treeScope 不同)
- 构建 DOM 树(Nodes -> DOM Tree)—— 最重要的工作是建立起每个结点的父子兄弟关系
-
样式计算
渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算出 DOM 节点的样式。
CSS 样式来源主要有 3 种,分别是通过 link 引用的外部 CSS 文件、style标签内的 CSS、元素的 style 属性内嵌的 CSS。
-
页面布局
布局过程,即
排除 script、meta 等功能化、非视觉节点,排除display: none的节点,计算元素的位置信息,确定元素的位置,构建一棵只包含可见元素布局树。如图:
其中,这个过程需要注意的是回流和重绘
-
生成分层树:对布局树进行分层,并生成分层树
页面中有很多复杂的效果,如一些复杂的 3D 变换、页面滚动,或者使用 z-indexing 做 z 轴排序等,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树(LayerTree)
-
栅格化
合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。
-
显示
合成线程发送绘制图块命令给浏览器进程。浏览器进程根据指令生成页面,并显示到显示