1. 用户输入 URL
用户在浏览器地址栏输入一个 URL,例如 https://www.example.com,并按下回车键。
2. 浏览器解析 URL
浏览器解析 URL,将其分解成不同的部分:
- 协议(Scheme):如
https - 用户名和密码:如
username:password@(用于身份验证,现代浏览器一般不再支持直接在 URL 中输入密码) - 域名(Host):如
www.example.com - 端口号(Port):如
:443(HTTPS 的默认端口为 443,HTTP 的默认端口为 80) - 路径(Path):如
/ - 查询参数(Query):如
?query=example - 片段标识符(Fragment):如
#section1
3. 检查缓存
浏览器会首先检查缓存中是否有该 URL 对应的资源,如果有且未过期,则直接使用缓存中的资源进行加载,省略后续步骤。
4. DNS 解析
如果缓存中没有对应的资源,浏览器会发起 DNS 解析,找到域名对应的 IP 地址。这个过程包括:
- 查找浏览器缓存:检查之前访问过的域名的缓存。
- 查找操作系统缓存:检查操作系统中的 DNS 缓存。
- 向路由器查询:路由器可能也有 DNS 缓存。
- 向 ISP 的 DNS 服务器查询:如果上述缓存中都没有找到,则向 ISP(互联网服务提供商)的 DNS 服务器发起查询。
- 递归查询:如果 ISP 的 DNS 服务器也没有找到,则会进行递归查询,最终找到权威 DNS 服务器,获取域名对应的 IP 地址。
DNS 递归查询过程
- 本地缓存:浏览器和操作系统缓存中查找记录。
- 路由器:向本地网络中的路由器查询。
- ISP 的 DNS 服务器:向互联网服务提供商的 DNS 服务器查询。
- 根 DNS 服务器:若 ISP 的 DNS 服务器未找到记录,向根 DNS 服务器查询。
- 顶级域名服务器(TLD):根服务器返回 TLD 服务器地址,如
.com、.net等。 - 权威 DNS 服务器:TLD 服务器返回权威 DNS 服务器地址,最终获取域名对应的 IP 地址。
5. 建立 TCP 连接
获取到 IP 地址后,浏览器与服务器之间建立 TCP 连接,通常需要三次握手过程:
- 客户端发送 SYN 包:请求建立连接。
- 服务器回应 SYN-ACK 包:表示同意建立连接。
- 客户端回应 ACK 包:确认连接建立。
三次握手
- SYN:客户端发送一个 SYN(同步序列号)包,请求建立连接。
- SYN-ACK:服务器收到 SYN 包,回应一个 SYN-ACK 包,表示同意建立连接并同步序列号。
- ACK:客户端收到 SYN-ACK 包,发送一个 ACK(确认)包,确认连接建立。
6. SSL/TLS 握手(如果是 HTTPS)
如果使用的是 HTTPS 协议,在 TCP 连接建立后,客户端和服务器还需要进行 SSL/TLS 握手,以建立安全的加密连接:
- ClientHello:客户端发送支持的协议版本、加密算法、压缩方法和一个随机数。
- ServerHello:服务器回应选择的协议版本、加密算法、压缩方法和一个随机数,并发送服务器证书。
- 证书验证:客户端验证服务器证书的合法性。
- 密钥交换:客户端生成一个 Pre-master Secret,用服务器的公钥加密并发送给服务器。
- 生成会话密钥:客户端和服务器根据 Pre-master Secret 生成对称加密的会话密钥。
- Finished:双方发送 Finished 消息,验证握手信息是否一致。
7. 发送 HTTP 请求
SSL/TLS 握手完成后,浏览器发送 HTTP 请求给服务器,通常包括以下内容:
- 请求行:如
GET / HTTP/1.1 - 请求头:包含用户代理、接受的语言、接受的文件类型等。
- 请求体:POST 请求等可能包含请求体数据。
HTTP/1.1 特性
- 持久连接:默认开启持久连接,可以复用一个 TCP 连接来发送和接收多个 HTTP 请求和响应。
- 管道化:支持请求管道化,可以在同一个连接上同时发送多个请求,但服务器必须按照请求顺序返回响应,实际中很少使用。
HTTP/2 特性
- 二进制分帧层:所有通信都是在一个 TCP 连接上完成,并通过二进制分帧层传输。
- 多路复用:在一个连接上可以同时发送多个请求和响应,而不需要按照顺序一一对应。
- 头部压缩:通过 HPACK 算法压缩头部,减少了传输的数据量。
- 服务器推送:服务器可以主动推送资源到客户端,减少后续请求的延迟。
8. 服务器处理请求
服务器接收到请求后,处理请求:
- 路由处理:根据请求路径找到对应的处理程序。
- 权限验证:检查用户是否有权限访问资源。
- 处理逻辑:执行具体的业务逻辑,可能涉及数据库查询等。
- 生成响应:生成 HTTP 响应,包括状态码、响应头和响应体。
9. 服务器发送响应
服务器将响应数据发送回客户端,通常包括:
- 状态行:如
HTTP/1.1 200 OK - 响应头:如内容类型、缓存控制等。
- 响应体:如 HTML 文档、JSON 数据等。
10. 浏览器接收响应
浏览器接收到服务器的响应后,进行以下处理:
- 检查状态码:如 200 表示成功,404 表示未找到,500 表示服务器错误等。
- 解析响应头:处理缓存控制、内容类型等信息。
- 解析响应体:根据内容类型解析响应体,例如 HTML 文档、CSS 样式表、JavaScript 文件、图像等。
11. 渲染页面
浏览器解析和渲染页面,涉及以下步骤:
解析 HTML
- 构建 DOM 树:将 HTML 文档解析为 DOM 树。
- 处理 CSS:解析 CSS 文件和内嵌样式,生成 CSSOM(CSS 对象模型)。
- 构建渲染树:结合 DOM 和 CSSOM,构建渲染树。
布局(Layout)
- 计算布局:根据渲染树计算每个元素的位置和大小。
绘制(Paint)
- 绘制元素:将每个元素绘制到屏幕上。
处理 JavaScript
- 下载和解析:下载和解析 JavaScript 文件。
- 执行脚本:执行 JavaScript 脚本,可能会修改 DOM 树,触发重新布局和重绘。
12. 加载外部资源
在解析 HTML 文档过程中,如果遇到外部资源(如 CSS、JavaScript、图像等),浏览器会发送额外的请求来加载这些资源,并进行相应的处理和渲染。
13. 执行完成
浏览器完成所有资源的加载和页面的渲染,用户看到完整的网页。页面加载完成后,浏览器还会继续监听用户交互事件,并处理后续的操作。
14. 连接关闭(四次挥手)
当页面加载完成并且不再需要保持连接时,浏览器和服务器会进行 TCP 四次挥手关闭连接:
- 客户端发送 FIN 包:请求关闭连接。
- 服务器回应 ACK 包:确认关闭请求,但仍可以发送未完成的数据。
- 服务器发送 FIN 包:通知客户端可以关闭连接。
- 客户端回应 ACK 包:确认服务器的关闭请求,连接关闭。
四次挥手
- FIN:客户端发送一个 FIN(结束)包,请求关闭连接。
- ACK:服务器收到 FIN 包,回应一个 ACK 包,确认收到关闭请求。
- FIN:服务器发送一个 FIN 包,通知客户端可以关闭连接。
- ACK:客户端收到 FIN 包,发送一个 ACK 包,确认服务器的关闭请求,连接关闭。