大致流程如下:
-
URL 解析
-
DNS 查询
-
TCP 连接
-
处理请求
-
接受响应
-
渲染页面
一、URL 解析
地址解析:首先判断你输入的是一个合法的 URL 还是一个待搜索的关键词,并且根据你输入的内容进行自动完成、字符编码等操作。
HSTS:由于安全隐患,会使用 HSTS 强制客户端使用 HTTPS 访问页面。详见:你所不知道的 HSTS[1]。
其他操作:浏览器还会进行一些额外的操作,比如安全检查、访问限制(之前国产浏览器限制 996.icu)。
检查缓存
二、DNS 查询
基本步骤:
1. 浏览器缓存
浏览器会先检查是否在缓存中,没有则调用系统库函数进行查询。
2. 操作系统缓存
操作系统也有自己的 DNS缓存,但在这之前,会先检查域名是否存在本地的 Hosts 文件里,没有则向 DNS 服务器发送查询请求。
3. 路由器缓存
路由器也有自己的缓存。
4. ISP DNS 缓存
ISP DNS 就是在客户端电脑上设置的首选 DNS 服务器,它们在大多数情况下都会有缓存。
5.根域名服务器查询
在前面所有步骤没有缓存的情况下,本地 DNS 服务器会将请求转发到互联网上的根域,下面这个图很好的诠释了整个流程:
需要注意的点
-
递归方式:一路查下去中间不返回,得到最终结果才返回信息(浏览器到本地DNS服务器的过程)
-
迭代方式,就是本地DNS服务器到根域名服务器查询的方式。
-
什么是 DNS 劫持
-
前端 dns-prefetch 优化
三、TCP 连接
TCP/IP 分为四层,在发送数据时,每层都要对数据进行封装:
1. 应用层:发送 HTTP 请求
在前面的步骤我们已经得到服务器的 IP 地址,浏览器会开始构造一个 HTTP 报文,其中包括:
-
-
请求报头(Request Header):请求方法、目标地址、遵循的协议等等
-
请求主体(其他参数)
-
其中需要注意的点:
-
-
浏览器只能发送 GET、POST 方法,而打开网页使用的是 GET 方法
-
2. 传输层:TCP 传输报文
在建立连接前,会先进行 TCP 三次握手。所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
3. 网络层:IP协议查询Mac地址
将数据段打包,并加入源及目标的IP地址,并且负责寻找传输路线。判断目标地址是否与当前地址处于同一网络中,是的话直接根据 Mac 地址发送,否则使用路由表查找下一跳地址,以及使用 ARP 协议查询它的 Mac 地址。
4. 链路层:以太网协议
以太网协议
根据以太网协议将数据分为以“帧”为单位的数据包,每一帧分为两个部分:
-
-
-
标头:数据包的发送者、接受者、数据类型
-
数据:数据包具体内容
-
-
Mac 地址
以太网规定了连入网络的所有设备都必须具备“网卡”接口,数据包都是从一块网卡传递到另一块网卡,网卡的地址就是 Mac 地址。每一个 Mac 地址都是独一无二的,具备了一对一的能力。
广播
发送数据的方法很原始,直接把数据通过 ARP 协议,向本网络的所有机器发送,接收方根据标头信息与自身 Mac 地址比较,一致就接受,否则丢弃。
注意:接收方回应是单播。
四、服务器处理请求
大致流程如下:
HTTPD
最常见的 HTTPD 有 Linux 上常用的 Apache 和 Nginx,以及 Windows 上的 IIS。
它会监听得到的请求,然后开启一个子进程去处理这个请求。
处理请求
接受 TCP 报文后,会对连接进行处理,对HTTP协议进行解析(请求方法、域名、路径等),并且进行一些验证:
-
-
-
验证是否配置虚拟主机
-
验证虚拟主机是否接受此方法
-
验证该用户可以使用该方法(根据 IP 地址、身份信息等)
-
-
重定向
假如服务器配置了 HTTP 重定向,就会返回一个 301
永久重定向响应,浏览器就会根据响应,重新发送 HTTP 请求(重新执行上面的过程)。
URL 重写
然后会查看 URL 重写规则,如果请求的文件是真实存在的,比如图片、html、css、js文件等,则会直接把这个文件返回。
否则服务器会按照规则把请求重写到 一个 REST 风格的 URL 上。
五、浏览器接受响应
浏览器接收到来自服务器的响应资源后,会对资源进行分析。
首先查看 Response header,根据不同状态码做不同的事(比如上面提到的重定向)。
如果响应资源进行了压缩(比如 gzip),还需要进行解压。
然后,对响应资源做缓存。
接下来,根据响应资源里的 MIME[3] 类型去解析响应内容(比如 HTML、Image各有不同的解析方式)。
六、渲染页面
- 解析HTML,构建DOM树
- 解析CSS,生成CSS规则树
- 合并DOM树和CSS规则,生成render树
- 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
- 绘制render树(paint),绘制页面像素信息
- 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上
七、关闭TCP连接或继续保持连接
四次挥手关闭连接:
所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示: