1. 用户输入 URL 或触发请求
当你在浏览器中输入一个 URL 或在应用程序中触发某个请求时,首先需要解析这个 URL,识别出协议、域名、路径等信息。
2. DNS 解析
计算机需要通过 域名系统(DNS) 将 URL 中的域名转换为 IP 地址。比如,输入 https://www.example.com
,DNS 会将 www.example.com
转换成对应的服务器 IP 地址,以便建立与目标服务器的连接。
3. 建立 TCP 连接
HTTP 是基于 TCP/IP 协议 的,因此客户端(比如浏览器)会与目标服务器建立一个 TCP 连接。通常,客户端和服务器之间的连接是通过三次握手来实现的:
- 客户端发送 SYN 请求:客户端向服务器发送一个请求,表示希望建立连接。
- 服务器返回 SYN-ACK 响应:服务器收到请求并同意建立连接,返回一个确认消息。
- 客户端发送 ACK 确认:客户端收到服务器的确认消息,并完成三次握手。
在这个过程中,客户端和服务器之间的 TCP 连接就被建立起来了。
4. 发送 HTTP 请求报文
一旦 TCP 连接建立,客户端会向服务器发送 HTTP 请求报文。这个报文包含以下几个部分:
- 请求行:包含请求方法(GET、POST、PUT、DELETE 等)、请求的 URL 路径以及 HTTP 版本(如
HTTP/1.1
)。 - 请求头:提供关于请求的额外信息,比如
Host
(目标服务器的域名)、User-Agent
(浏览器类型)、Content-Type
(请求体的类型)等。 - 请求体(可选):如果请求方法是
POST
或PUT
,请求体中会包含要发送的数据,比如表单数据、JSON 数据等。
5. 服务器处理请求
服务器收到 HTTP 请求后,会根据请求的内容做出响应。这个过程包括:
- 解析请求报文。
- 执行相关的逻辑,比如查询数据库、处理表单数据、返回静态资源等。
- 生成 HTTP 响应报文。
6. 发送 HTTP 响应报文
服务器处理完请求后,会通过 TCP 连接向客户端返回一个 HTTP 响应报文。这个报文通常包含以下几个部分:
- 响应状态行:包括 HTTP 版本(如
HTTP/1.1
)、状态码(如 200 表示成功,404 表示未找到,500 表示服务器错误等)和状态描述(如 OK、Not Found)。 - 响应头:包含一些描述响应的元信息,比如
Content-Type
(响应内容类型)、Content-Length
(响应体长度)、Set-Cookie
(设置 Cookie)等。 - 响应体:包含实际的响应内容,比如 HTML 页面、JSON 数据、图片文件等。
7. 浏览器渲染响应内容
一旦浏览器收到服务器返回的响应数据,它会进行解析和渲染:
- 如果响应是 HTML 页面,浏览器会解析 HTML、CSS、JavaScript,并通过渲染引擎将页面展示给用户。
- 如果响应是其他类型的数据(比如 JSON、图片、视频等),浏览器会根据内容类型进行相应的处理。
8. 关闭连接或复用连接
根据 HTTP 版本(HTTP/1.1 或 HTTP/2)以及请求的设置(如 Connection: keep-alive
),连接可能会被保持活跃,供后续请求复用。否则,在响应完成后,客户端和服务器会关闭 TCP 连接。
- HTTP/1.0 默认在每次请求后关闭连接,但可以通过在请求头中指定
Connection: keep-alive
来保持连接。 - HTTP/1.1 默认会保持连接,直到客户端或服务器显式关闭。
- HTTP/2 则采用了更高效的多路复用机制,允许在单一的连接上并行处理多个请求和响应。
9. 缓存处理(可选)
在整个过程中,浏览器和服务器可能会利用缓存来减少不必要的请求。比如:
- 浏览器缓存:浏览器会缓存一些资源(如图片、CSS 文件等),如果用户再次请求相同的资源,浏览器会直接从缓存中加载,而不是重新请求服务器。
- 服务器缓存:服务器可能会根据缓存策略(如 ETag、Cache-Control)判断是否返回缓存的内容。
10. 关闭 TCP 连接
如果连接不需要复用,客户端和服务器通过四次挥手关闭 TCP 连接:
- 客户端发送 FIN 请求:客户端通知服务器,它已经完成数据发送。
- 服务器响应 ACK:服务器确认客户端的请求。
- 服务器发送 FIN 请求:服务器通知客户端,服务器的数据也已发送完毕。
- 客户端响应 ACK:客户端确认服务器的请求。