在浏览器输入URL之后的流程大体分为六步:
- DNS解析
- 发起TCP连接(三次握手)
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 关闭连接请求(四次挥手)
这里用一张可视化图表来演示流程
1. DNS解析
DNS解析就是寻找在哪台主机上有你需要的资源的过程, 也就是寻找输入域名的ip地址。
浏览器会首先检查本地的缓存和本地host文件, 有没有该域名的ip地址, 如果有,就直接使用; 如果没有, 本地的DNS客户端就会向本地的DNS服务器(比如中国电信\中国移动) 发送请求, 询问他们输入域名对应的ip地址是多少, 同样地,本地DNS服务器会先查看他自己的缓存记录, 如果有就直接返回, 如果没有, 就继续向根域名服务器查询\顶级域名服务器\权威域名服务器。
2. 发起TCP连接(三次握手)
三次握手的机制是为了建立起一个安全可靠的连接, 客户端和服务端都要保证自己能够发送数据和接受数据。
与四次握手不同, 三次握手是首先由客户端发起的, 客户端首先给服务端发送一个syn报文, 当服务端收到之后,他就知道客户端想要建立一个新的连接, 于是服务端会给客户端发送一个ack位置1, 以及syn位置1的消息确认包, 当客户端收到确认包之后, 客户端就知道了我既能发送数据又能接收数据。
但这个时候服务端只知道自己能接受数据, 还不能确认自己发送的数据, 客户端能不能接收得到, 所以客户端还需要给服务端发送一个ack位置1的报文, 也就是第三次握手。
完成以上操作后, 三次握手就正式结束了, 双方建立起了一个安全可靠的连接。
3. 发送HTTP请求
在成功建立TCP连接后,客户端(通常是浏览器)会发送一个HTTP请求到服务器。
这个HTTP请求包含了很多信息,比如请求的方法(GET、POST等)、请求的资源路径(URL)、HTTP版本(如HTTP/1.1)、请求头部(Headers)等。
请求头部可以包含很多元数据,比如客户端的类型、支持的压缩方式、缓存策略、Cookie等。这些信息有助于服务器理解和处理请求。
4. 服务器处理请求并返回HTTP报文
服务器接收到HTTP请求后,会根据请求的内容进行相应的处理。这可能包括查询数据库、执行程序逻辑、读取文件等。
处理完成后,服务器会生成一个HTTP响应报文,并将其发送回客户端。这个响应报文同样包含很多信息,比如HTTP状态码(如200表示成功、404表示未找到资源)、响应头部(Headers)、响应体(Body)等。
响应头部可以包含内容类型、内容长度、缓存策略等信息。响应体则包含了实际的数据,比如HTML文档、图片、JSON数据等。
5. 浏览器解析渲染页面
浏览器接收到服务器的HTTP响应后,会开始解析响应报文。如果响应体是HTML文档,浏览器会按照HTML文档的结构来渲染页面。
渲染过程中,浏览器可能会遇到需要加载的外部资源,比如CSS样式表、JavaScript脚本、图片等。这时,浏览器会再次发起HTTP请求来获取这些资源,并依次解析和渲染。
渲染完成后,用户就可以在浏览器中看到完整的网页了。
步骤 | 简要说明 |
---|---|
1.解析HTML | 解析完会得到DOM树和CSSOM树 |
2.样式计算 | 遍历得到的DOM树,根据样式优先级规则为树中的每个节点计算出它最终的样式,得到一颗带有样式的DOM树 |
3.布局(flow) | 依次遍历DOM树的每一个节点, 计算每个节点的几何信息, 得到布局树 |
4.分层 | 分层的好处在于, 将来某一个层改变后, 仅会对该层进行后续处理,从而提升效率。而滚动条, 堆叠上下文, transform, opacity 等样式都会或多或少的影响分层结果, 也可以通过will-change 属性更大程度地影响分层结果 |
5.绘制(paint) | 为每个层单独产生绘制指令集, 用于描述这一层的内容该如何 ‘画’ 出来 |
6.分块 | 前面5个步骤主要是工作在渲染主线程中, 完成绘制后, 主线程会将每个图层的绘制信息提交给合成线程, 剩余工作将由合成线程完成。合成线程首先对每个图层进行分块, 将其划分为更多的小区域, 再从线程池中调动多个线程来完成分块工作 |
7.光栅化 | 合成线程会将块信息交给GPU进程,以极高的速度完成光栅化。而GPU进程会调动多个线程来完成光栅化, 并且优先处理靠近视口区域的块 |
8.画 | 合成线程拿到每个层,每个块的位图后,生成一个个 指引(quad) 信息, 然后将quad提交给GPU进程, 由GPU进程产生系统调用, 提交给GPU硬件,完成最终的屏幕成像。 |
6. 关闭连接请求(四次挥手)
四次挥手呢可以由任意的一方发起, 假设发起方是客户端
挥手 | 说明 |
---|---|
第一次 | 客户端就会发送一个fin位置1的报文, 当服务端收到该报文就会知道客户端想要断开连接, |
第二次 | 但这个时候服务端不一定能够做好准备, 因为此时服务端很有可能有一些未发送完的消息, 所以此时服务端只能进行一个消息的确认, 给客户端先发送一个ack报文, 让客户端知道我这边知道你想要断开连接了, 但我还有数据没有发送完, 等我发送完之后再联系你。 |
第三次 | 当服务端发送完数据就会再给客户端发送一个fin报文,表示数据发完了, 可以断开连接 |
第四次 | 客户端收到之后还需要再给服务端发送一个ack报文, 也就是第四次挥手, 表示收到了, 至此正式完成断开连接。 |