当你在浏览器地址栏敲下www.baidu.com并按下回车,短短几秒内页面就展现在眼前。这个看似简单的过程,背后是计算机网络、操作系统、浏览器内核等多层系统协同工作的结果。
本文将以 “输入 URL 到页面显示” 为主线,从底层原理拆解全过程,涉及 DNS 解析、TCP 握手、TLS 加密、HTTP 交互、页面渲染等 11 个核心环节,每个步骤都深入到协议细节和实现逻辑,帮你建立完整的技术知识链 —— 这也是前端 / 后端 / 客户端面试中常考的 “底层连环问” 核心内容。
一、URL 解析:把 “模糊输入” 变成 “精确指令”
你以为输入的是www.baidu.com,但浏览器第一步要做的是 “标准化” 这个字符串,把它转换成计算机能理解的 “网络地址”。这一步看似简单,却包含了浏览器对用户输入习惯的深度适配。
1. 补全协议:默认填充 http/https
浏览器会先判断 URL 是否包含协议(http://或https://)。如果没有,会根据域名特性自动补全:
- 对于常见域名(如
baidu.com、google.com),现代浏览器默认补全https://(因 HTTPS 更安全,且主流网站已支持); - 对于本地服务(如
localhost:3000),可能补全http://(开发环境通常不配置 HTTPS)。
例如,输入www.baidu.com会被解析为https://www.baidu.com/。
2. 拆分 URL 结构:按规则拆解成 6 部分
URL(Uniform Resource Locator)的标准结构是:
协议://用户名:密码@域名:端口/路径?查询参数#哈希
浏览器会按此规则拆分输入,提取关键信息:
- 协议(scheme) :
https(决定使用的应用层协议); - 域名(host) :
www.baidu.com(需要解析为 IP 的核心部分); - 端口(port) :HTTPS 默认 443,HTTP 默认 80(若 URL 未指定则自动填充);
- 路径(path) :
/(默认根路径,若输入www.baidu.com/s?wd=test则路径为/s); - 查询参数(query) :
wd=test(键值对,用于向服务器传递参数); - 哈希(fragment) :如
#top(用于页面内锚点定位,不会发送到服务器)。
例如,https://user:pass@www.baidu.com:443/s?wd=test#top会被拆分为上述 6 部分,后续步骤会基于这些信息发起请求。
3. 特殊情况处理:兼容用户的 “不规范输入”
浏览器会容错处理非标准输入:
- 若输入的是 IP 地址(如
183.2.172.177),则跳过 DNS 解析,直接使用该 IP; - 若输入的是关键词(如 “百度”),则自动跳转到默认搜索引擎(如
https://www.baidu.com/s?wd=百度); - 若包含非法字符(如空格),则自动进行 URL 编码(空格→
%20)。 - 如果 URL 以
file://开头(如file:///C:/index.html),浏览器会直接读取本地文件,跳过后续的网络请求流程。
小结:URL 解析的核心是 “标准化”—— 将用户的模糊输入转换为包含协议、域名、端口等要素的精确地址,为后续的网络请求铺路。
二、DNS 解析:把 “域名” 翻译成 “IP 地址”
人类擅长记忆有意义的字符串(如www.baidu.com),但计算机之间通信只能通过 IP 地址(如183.2.172.177)。DNS(Domain Name System)的作用,就是完成 “域名→IP” 的翻译,这是整个流程中最基础也最关键的一步。
1. DNS 解析的本质:分布式键值对数据库
DNS 不是一个单一的服务器,而是由全球数百万台服务器组成的 “分布式数据库”,核心功能是存储 “域名→IP” 的映射关系。它的设计遵循 “分层缓存 + 分布式查询” 原则,确保解析高效且可靠。
2. 解析流程:从 “本地缓存” 到 “根服务器” 的 5 层查询
当浏览器需要解析www.baidu.com时,会按以下顺序查询,直到获取 IP:
(1)浏览器 DNS 缓存:最快的 “本地记忆”
浏览器会先检查自身缓存(Chrome 可通过chrome://net-internals/#dns查看)。
- 缓存来源:之前解析过的域名,会被浏览器暂存(TTL 值决定缓存时间,通常几分钟到几小时);
- 优点:无需网络请求,耗时 < 1ms;
- 缺点:容量有限(Chrome 约存 1000 条),且缓存时间短。
若缓存中存在
www.baidu.com的 IP,则直接使用,跳过后续步骤。
(2)操作系统 DNS 缓存:系统级 “共享记忆”
若浏览器缓存未命中,会查询操作系统的 DNS 缓存(Windows 可通过ipconfig /displaydns查看,Linux 通过systemd-resolve --statistics)。
- 缓存来源:操作系统为所有应用共享,记录了本机最近解析过的域名;
- 典型场景:同一台电脑的 Chrome 和 Firefox 浏览器,会共享操作系统缓存的 DNS 记录。
(3)Hosts 文件:手动配置的 “强制映射”
若系统缓存未命中,浏览器会读取操作系统的hosts文件(Windows 路径C:\Windows\System32\drivers\etc\hosts,Linux 路径/etc/hosts)。
- 作用:允许用户手动指定 “域名→IP” 映射(格式:
IP 域名,如127.0.0.1 www.test.com); - 开发场景:前端开发时,可将线上域名(如
www.company.com)映射到本地 IP(127.0.0.1),实现在本地调试线上环境的效果,避免污染真实服务器。
若hosts文件中存在www.baidu.com的配置,则直接使用指定 IP。
(4)递归 DNS 服务器:“中间人” 代为查询
若前三层都未命中,浏览器会向 “递归 DNS 服务器” 发送查询请求。
- 什么是递归 DNS 服务器?通常是你的网络服务商(ISP)提供的服务器(如电信、联通),或公共 DNS(如 114.114.114.114、8.8.8.8);
- 作用:代替用户完成后续的复杂查询(用户只需等待结果,无需关心中间过程)。
例如,你的电脑连接家里的 WiFi 后,路由器会自动分配电信的递归 DNS 服务器 IP(如202.96.128.86),浏览器会将查询请求发送到该服务器。
(5)根服务器→顶级域名服务器→权威服务器:分布式查询链
递归 DNS 服务器也没有www.baidu.com的记录时,会启动 “迭代查询”,逐级向更高层级的 DNS 服务器请求:
- 第一步:查询根服务器(Root Server)
根服务器是 DNS 系统的 “总入口”,全球共 13 组(编号 A-M),由不同机构管理(如美国 Verisign、中国阿里云等)。
递归服务器会向根服务器发送请求:“请问www.baidu.com的 IP 是什么?”
根服务器不直接存储具体域名的 IP,而是返回 “顶级域名服务器” 的地址:“.com域名由这些服务器管理,你去问它们→[a.gtld-servers.net, ...]”。 - 第二步:查询顶级域名服务器(TLD Server)
顶级域名是域名中最右边的部分(如.com、.cn、.org),对应的服务器存储该顶级域名下所有二级域名的信息。
递归服务器向.com顶级服务器发送请求:“请问www.baidu.com的 IP 是什么?”
顶级服务器返回 “权威服务器” 的地址:“baidu.com由这些服务器管理,你去问它们→[dns.baidu.com, ...]”。 - 第三步:查询权威服务器(Authoritative Server)
权威服务器是域名的 “真正管理者”,由域名持有者配置(如百度会为baidu.com设置自己的 DNS 服务器)。
递归服务器向百度的权威服务器(如dns.baidu.com)发送请求:“请问www.baidu.com的 IP 是什么?”
权威服务器返回最终 IP:“www.baidu.com对应的 IP 是183.2.172.177”。
(6)结果返回与缓存
递归 DNS 服务器拿到 IP 后,会将结果返回给浏览器,同时将该 “域名→IP” 映射缓存(TTL 通常为几分钟到几小时),以便后续其他用户查询时加速。
3. 特殊现象:域名解析的 “不确定性”
用ping www.baidu.com时,你可能会发现返回的域名是www.a.shifen.com(如PING www.a.shifen.com (183.2.172.177)),这是因为:
- 百度为了负载均衡和安全,将
www.baidu.com通过 CNAME 记录(别名记录)指向www.a.shifen.com,后者才是实际提供服务的域名; - 同一域名在不同时间、不同地区解析出的 IP 可能不同(通过 DNS 轮询实现负载均衡,让用户访问就近的服务器)。
4. DNS 优化:提前解析,减少等待
为加速后续请求,浏览器会通过以下方式优化 DNS 解析:
- DNS 预解析(dns-prefetch)
在 HTML 中通过<link rel="dns-prefetch" href="//g.alicdn.com">告知浏览器:“提前解析g.alicdn.com的 IP”。当页面后续需要请求该域名的资源时,可直接使用缓存的 IP,节省解析时间。
适用场景:页面中会用到的第三方域名(如 CDN、广告服务)。 - 预连接(preconnect)
<link rel="preconnect" href="//unpkg.byted-static.com">不仅会提前解析 DNS,还会提前建立 TCP 连接和 TLS 会话(若为 HTTPS),进一步减少后续请求的延迟。
原理:DNS 解析→TCP 握手→TLS 握手是串行过程,预连接将其提前到页面加载初期,与其他资源加载并行进行。
小结:DNS 解析是 “从本地到全球” 的分层查询过程,通过多级缓存和分布式服务器,在确保可靠性的同时最大化解析效率。理解这一过程,是优化网络请求性能的基础。
三、判断是否为 HTTPS:决定使用的安全协议
DNS 解析得到 IP 后,浏览器需要根据 URL 的协议(http或https)决定使用的通信方式。这一步直接影响后续的连接建立过程(HTTP 用 TCP,HTTPS 用 TCP+TLS)。
1. 协议区别:HTTP vs HTTPS
- HTTP(HyperText Transfer Protocol) :超文本传输协议,明文传输数据,端口默认 80;
- HTTPS(HTTP Secure) :在 HTTP 基础上加入 TLS(Transport Layer Security)加密层,所有数据加密传输,端口默认 443。
现代浏览器对 HTTPS 的支持更友好(如 Chrome 会对 HTTP 网站标记 “不安全”),因此主流网站均已采用 HTTPS。
2. HTTPS 的核心价值:加密 + 认证 + 完整性
HTTPS 通过 TLS 实现三大安全目标:
- 加密:防止数据在传输过程中被窃听(如黑客截获 WiFi 中的数据);
- 认证:确保客户端连接的是真实服务器(防止 “中间人攻击”);
- 完整性:确保数据在传输过程中未被篡改(如黑客修改网页内容)。
小结:协议类型决定了后续连接的安全级别 —— HTTP 需先建立 TCP 连接,之后直接在 TCP 连接上传输数据;HTTPS 同样先建立 TCP 连接,再在 TCP 连接基础上完成 TLS 握手(加密协商),随后通过 “TCP 连接 + TLS 加密层” 传输数据。
四、建立 TCP 连接:三次握手的 “安全约定”
无论是 HTTP 还是 HTTPS,底层都依赖 TCP(Transmission Control Protocol)协议传输数据。TCP 是一种 “可靠的、面向连接的协议”,在传输数据前,必须通过 “三次握手” 建立连接。
1. 三次握手的本质:确认双方 “收发能力正常”
TCP 连接的建立需要客户端和服务器交换三个报文,目的是确保双方的发送和接收能力都正常,避免无效连接。
以 “浏览器(客户端)向百度服务器(服务器)建立连接” 为例:
(1)第一次握手(客户端→服务器):“我想连接你”
-
客户端发送SYN 报文(同步报文段),包含:
- 标志位:
SYN=1(表示这是一个连接请求); - 初始序列号(ISN,Initial Sequence Number):随机生成的 32 位整数(如
x),用于后续数据传输的编号(确保数据有序)。
- 标志位:
-
服务器收到后,知道 “客户端能发送数据”。
(2)第二次握手(服务器→客户端):“我同意连接,你能收到吗”
-
服务器返回SYN+ACK 报文,包含:
- 标志位:
SYN=1(表示服务器同意建立连接),ACK=1(确认收到客户端的报文); - 服务器的初始序列号(如
y); - 确认号:
x+1(表示已收到客户端到x的所有数据,下一次期望收到x+1)。
- 标志位:
-
客户端收到后,知道 “服务器能接收数据,且服务器能发送数据”。
(3)第三次握手(客户端→服务器):“我能收到,开始吧”
-
客户端返回ACK 报文,包含:
- 标志位:
ACK=1(确认收到服务器的报文); - 确认号:
y+1(表示已收到服务器到y的所有数据,下一次期望收到y+1)。
- 标志位:
-
服务器收到后,知道 “客户端能接收数据”。
2. 为什么需要三次握手?
核心是为了防止 “已失效的连接请求” 被服务器接收:
- 假设客户端发送的第一个 SYN 报文因网络延迟滞留,客户端超时后重新发送 SYN 并建立连接;
- 若没有第三次握手,当滞留的 SYN 报文到达服务器时,服务器会误以为是新的连接请求,建立无效连接,浪费资源;
- 三次握手确保只有双方都确认 “收发正常” 后,才会正式建立连接,避免上述问题。
3. 实际传输中的细节
- 序列号(Sequence Number) :每传输一个字节,序列号 + 1(如发送 100 字节,序列号从
x变为x+100),用于确保数据有序且不丢失; - 窗口大小(Window Size) :报文中包含 “接收窗口大小”,用于流量控制(告知对方 “我最多能接收多少字节”,避免发送方发送过快导致接收方缓冲区溢出);
- MSS(Maximum Segment Size) :最大报文段长度(通常为 1460 字节),决定了每个 TCP 报文能承载的最大数据量(受 MTU 限制,以太网 MTU 为 1500 字节,减去 TCP 头部 20 字节和 IP 头部 20 字节,剩余 1460 字节)。
小结:三次握手是 TCP 可靠性的基础,通过三次报文交换,双方确认彼此的收发能力,为后续数据传输建立 “安全通道”。
五、HTTPS 的 TLS 握手:给数据 “穿上加密外衣”
如果是 HTTPS 协议,在 TCP 三次握手后,还需要进行 TLS 握手(TLS Handshake)—— 客户端和服务器协商加密算法、交换密钥,确保后续传输的数据都是加密的。
以 TLS 1.3(目前最主流的版本,相比 TLS 1.2 更高效)为例,拆解握手过程:
1. TLS 握手的核心目标
- 协商加密算法(如对称加密用 AES,非对称加密用 RSA 或 ECDH);
- 服务器向客户端证明身份(通过 SSL 证书);
- 生成双方共享的 “会话密钥”(用于后续对称加密传输数据)。
2. TLS 1.3 握手的 4 个关键步骤
(1)客户端问候(Client Hello)
客户端向服务器发送报文,包含:
- 支持的 TLS 版本(如 TLS 1.3);
- 支持的加密套件列表(如
TLS_AES_256_GCM_SHA384,包含对称加密、非对称加密、哈希算法); - 客户端随机数(
client_random,32 字节,用于后续生成会话密钥); - 扩展字段(如
ALPN告知服务器支持的应用层协议,如 HTTP/2)。
(2)服务器问候 + 证书 + 密钥交换(Server Hello + Certificate + Key Share)
服务器收到客户端问候后,返回三个关键信息:
-
Server Hello:
确认使用的 TLS 版本(如 TLS 1.3)和加密套件(如TLS_AES_256_GCM_SHA384),并发送服务器随机数(server_random,32 字节)。 -
Certificate:
服务器发送 SSL 证书(由 CA 机构颁发),包含:- 服务器域名(确保客户端连接的是正确域名);
- 服务器的公钥(非对称加密的公钥,用于加密后续的密钥交换);
- CA 机构的签名(证明证书的真实性)。
-
Key Share:
服务器生成 “椭圆曲线公钥”(ECDH 算法),发送给客户端(用于与客户端的私钥计算共享密钥)。
(3)客户端验证证书 + 密钥交换 +-finished
客户端收到服务器响应后,执行以下操作:
-
验证证书:
- 检查证书是否由可信 CA 机构颁发(浏览器内置了可信 CA 的根证书);
- 检查证书是否过期;
- 检查证书中的域名是否与当前访问的域名一致(防止 “域名劫持”);
- 用 CA 的公钥验证证书上的签名(确保证书未被篡改)。
若验证失败,浏览器会显示 “证书错误” 警告(如访问自签名证书的网站)。
-
计算会话密钥:
客户端用自己的椭圆曲线私钥和服务器的椭圆曲线公钥,计算出 “预主密钥(pre-master secret)”,再结合client_random和server_random,生成最终的 “会话密钥(master secret)”(对称加密密钥,用于后续数据传输)。 -
发送 Finished 报文:
客户端用会话密钥加密 “客户端已完成握手” 的消息,发送给服务器(证明客户端已正确生成会话密钥)。
(4)服务器验证 + finished
服务器用自己的椭圆曲线私钥和客户端的公钥计算出相同的会话密钥,解密客户端的 Finished 报文,确认客户端已就绪。
服务器再用会话密钥加密 “服务器已完成握手” 的消息,发送给客户端。
3. TLS 握手的优化:会话复用
TLS 握手耗时约 100-500ms(取决于网络),为减少重复握手的开销,浏览器和服务器会通过 “会话复用” 优化:
- 会话 ID:服务器为每个会话分配唯一 ID,客户端下次连接时发送该 ID,若服务器仍保留会话信息,则直接复用会话密钥,跳过证书验证和密钥交换;
- 会话票据(TLS Session Ticket) :服务器用密钥加密会话信息生成票据,客户端存储票据,下次连接时发送,服务器解密后复用会话。
小结:TLS 握手是 HTTPS 安全的核心,通过非对称加密交换密钥、证书验证身份,最终用对称加密传输数据(对称加密效率高于非对称加密),在安全和性能间取得平衡。
六、发送 HTTP 请求:构建 “请求报文” 并传输
完成 TCP(或 TCP+TLS)连接后,浏览器终于可以向服务器发送 HTTP 请求了。HTTP 请求是客户端向服务器传递 “需求” 的载体,包含请求行、请求头、请求体三部分。
1. 请求行(Request Line):明确 “请求方法 + 路径 + 协议版本”
格式:方法 路径 协议版本
-
方法(Method) :表示请求的目的,常见的有:
GET:获取资源(如请求 HTML、CSS),无请求体,参数在 URL 中;POST:提交数据(如表单提交),参数在请求体中;HEAD:类似 GET,但只返回响应头(用于检查资源是否存在);PUT/DELETE:修改 / 删除资源(RESTful API 常用)。
-
路径(Path) :请求的资源路径(如
/s、/api/user); -
协议版本:如
HTTP/1.1、HTTP/2(决定支持的特性,如 HTTP/2 的多路复用)。
示例:GET /s?wd=test HTTP/1.1(用 GET 方法请求/s路径,参数wd=test,使用 HTTP/1.1 协议)。
2. 请求头(Request Headers):传递 “附加信息”
请求头是键值对格式,用于向服务器传递客户端信息、请求条件等,常见字段:
Host:目标域名(如www.baidu.com,HTTP/1.1 要求必须包含,用于服务器在一台主机上部署多个域名时区分站点);User-Agent:客户端标识(如Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/116.0.0.0 Safari/537.36,服务器可根据其返回适配不同设备的内容);Accept:客户端可接受的响应数据类型(如text/html,application/json);Accept-Encoding:客户端支持的压缩算法(如gzip,deflate,服务器会用对应的算法压缩响应体,减少传输量);Cookie:客户端存储的 Cookie(键值对,如BAIDUID=xxx; BIDUPSID=xxx,用于身份认证、会话管理);Connection:是否保持连接(keep-alive表示 TCP 连接在请求后不关闭,可复用为后续请求);Referer:当前请求的来源页面(如从www.google.com跳转到百度,Referer 为https://www.google.com,用于防盗链、统计来源)。
3. 请求体(Request Body):携带 “请求数据”
请求体仅在POST、PUT等方法中存在,用于传递客户端提交的数据,常见格式:
application/x-www-form-urlencoded:表单默认格式(如name=test&age=18);multipart/form-data:用于上传文件(包含边界标识,区分不同字段);application/json:JSON 格式(RESTful API 常用,如{"name":"test","age":18})。
4. 实际请求示例(GET vs POST)
GET 请求(无请求体):
GET /s?wd=test HTTP/1.1
Host: www.baidu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/116.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Cookie: BAIDUID=xxx; BIDUPSID=xxx
Connection: keep-alive
POST 请求(有请求体):
POST /api/login HTTP/1.1
Host: www.baidu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/116.0.0.0 Safari/537.36
Accept: application/json
Content-Type: application/json
Content-Length: 36
Connection: keep-alive
{"username":"test","password":"123456"}
小结:HTTP 请求是客户端与服务器的 “沟通语言”,请求行明确目的,请求头传递上下文,请求体携带数据,三者共同确保服务器能准确理解并处理请求。
七、服务器处理请求:从 “接收” 到 “生成响应”
服务器收到 HTTP 请求后,需要经过一系列处理(负载均衡、路由匹配、业务逻辑、数据库交互等),最终生成响应返回给客户端。这个过程因服务器架构不同而有所差异,但核心逻辑一致。
1. 负载均衡:“分流” 到合适的服务器
大型网站(如百度、淘宝)的后端通常由多台服务器组成,请求首先会到达 “负载均衡器”(如 Nginx、F5),由其决定将请求转发到哪台服务器:
-
负载均衡的作用:
- 避免单台服务器过载(分流压力);
- 实现容灾(某台服务器故障时,自动转发到其他服务器);
- 就近访问(将用户请求转发到距离最近的机房服务器,降低延迟)。
-
常见算法:
- 轮询(按顺序依次转发);
- 权重(性能好的服务器分配更多请求);
- IP 哈希(同一 IP 的请求固定转发到同一服务器,保证会话一致性)。
2. 路由匹配:找到 “处理请求的模块”
服务器(如 Node.js 的 Express、Java 的 Spring)会根据请求的路径(Path)和方法(Method),匹配对应的处理函数(路由):
- 例如,
GET /s的请求会匹配百度搜索的处理逻辑; POST /api/login的请求会匹配登录验证的处理逻辑。
3. 业务逻辑处理:完成 “用户需求”
路由匹配后,服务器会执行对应的业务逻辑:
-
若为静态资源请求(如
/style.css),直接从文件系统读取资源; -
若为动态请求(如
/api/user),可能需要:- 验证用户身份(检查 Cookie 或 Token);
- 查询数据库(如从 MySQL 中获取用户信息);
- 调用第三方服务(如调用支付接口、短信接口);
- 处理数据(计算、格式化等)。
4. 生成响应:构建 “响应报文”
业务逻辑处理完成后,服务器生成 HTTP 响应,包含响应行、响应头、响应体三部分:
-
响应行(Status Line) :
协议版本 状态码 状态描述- 状态码(Status Code):表示请求处理结果,如
200(成功)、404(资源不存在)、500(服务器错误); - 示例:
HTTP/1.1 200 OK。
- 状态码(Status Code):表示请求处理结果,如
-
响应头(Response Headers) :传递服务器信息、响应属性等,常见字段:
Content-Type:响应体的 MIME 类型(如text/html; charset=utf-8、application/json);Content-Length:响应体的长度(字节数);Content-Encoding:响应体的压缩算法(如gzip,客户端需解压后再处理);Set-Cookie:服务器向客户端设置 Cookie(如BAIDUID=xxx; expires=...);Cache-Control:缓存策略(如max-age=3600表示缓存 1 小时);Location:重定向地址(配合301/302状态码使用)。
-
响应体(Response Body) :实际返回的数据,如 HTML 文档、JSON 字符串、图片二进制数据等。
小结:服务器处理请求是 “理解需求→执行逻辑→返回结果” 的过程,负载均衡确保可靠性,路由匹配确保请求被正确处理,业务逻辑实现核心功能。
八、客户端接收响应:处理 “服务器返回的数据”
浏览器收到服务器的响应后,需要根据响应内容进行处理 —— 若为 HTML 则渲染页面,若为 JSON 则交给 JavaScript 处理,若为图片则直接展示。
1. 处理响应状态码:判断请求是否成功
浏览器首先检查响应状态码,决定后续操作: 、
2xx(成功):继续处理响应体(如200 OK);3xx(重定向):根据Location头跳转(如301 Moved Permanently表示永久重定向,302 Found表示临时重定向);4xx(客户端错误):提示错误(如404 Not Found表示资源不存在,403 Forbidden表示权限不足);5xx(服务器错误):提示服务器异常(如500 Internal Server Error)。
2. 处理响应头:解析缓存、Cookie 等信息
- Cookie 处理:若响应头包含
Set-Cookie,浏览器会将其存储到本地 Cookie 数据库(按域名隔离),后续请求时自动带上; - 缓存处理:根据
Cache-Control、Expires等头信息,决定是否缓存响应体(静态资源通常会被缓存,减少后续请求); - 解压处理:若
Content-Encoding为gzip,浏览器会先解压响应体,再进行后续处理。
3. 处理响应体:根据 Content-Type 解析数据
浏览器根据Content-Type决定如何解析响应体:
text/html:交给 HTML 解析器处理,构建 DOM 树;text/css:交给 CSS 解析器处理,构建 CSSOM 树;application/json:解析为 JavaScript 对象,交给业务逻辑处理;image/jpeg/image/png:解码为图片像素数据,用于渲染;application/javascript:作为 JavaScript 代码执行(可能会修改 DOM/CSSOM)。
小结:客户端接收响应后,先通过状态码判断结果,再解析响应头处理缓存和 Cookie,最后根据内容类型解析响应体,为页面渲染或业务逻辑提供数据。
九、页面渲染:从 “HTML 字符串” 到 “像素画面”
如果响应体是 HTML(Content-Type: text/html),浏览器会启动渲染引擎(如 Chrome 的 Blink),将 HTML 字符串转换为用户可见的页面。这是前端开发者最关注的环节,涉及 DOM、CSSOM、渲染树、回流、重绘等核心概念。
1. 解析 HTML:构建 DOM 树(Document Object Model)
HTML 解析器逐行解析 HTML 字符串,将标签转换为 “DOM 节点”,并构建成树状结构(DOM 树):
- 过程:读取字符→识别标签(如
<div>)→创建节点→添加到 DOM 树; - 特点:HTML 解析是 “增量解析”(边下载边解析),无需等待整个 HTML 下载完成;
- 阻塞:解析过程中若遇到
<script>标签(无defer/async),会暂停 HTML 解析,先执行 JavaScript(因 JS 可能修改 DOM,如document.write)。
2. 解析 CSS:构建 CSSOM 树(CSS Object Model)
CSS 解析器解析<style>标签、<link rel="stylesheet">引入的 CSS,构建 CSSOM 树:
- 作用:存储所有 CSS 规则,每个节点包含该节点的样式信息(如颜色、字体、尺寸);
- 特点:CSS 解析是 “阻塞渲染” 的(需等待 CSSOM 构建完成才能生成渲染树),但不阻塞 HTML 解析(可并行进行);
- 优化:通过
media="print"标记打印样式,不会阻塞屏幕渲染。
3. 构建渲染树(Render Tree):关联 DOM 和 CSSOM
渲染树是 DOM 树和 CSSOM 树的结合,只包含 “可见元素”(隐藏元素如display: none不会进入渲染树):
- 过程:遍历 DOM 树→为每个可见节点匹配 CSSOM 中的样式规则→生成渲染树节点(包含样式信息);
- 作用:为后续的 “布局” 和 “绘制” 提供数据。
4. 布局(Layout):计算 “元素位置和尺寸”
布局(又称 “回流” 或 “重排”)是根据渲染树计算每个元素的几何信息(位置、宽度、高度、距离视口的距离等):
- 触发因素:DOM 结构变化(如添加节点)、样式变化(如
width、margin)、窗口大小变化; - 特点:布局是 “递归的”(父元素尺寸变化会影响子元素),耗时与元素数量正相关(优化需减少布局范围)。
5. 绘制(Paint):将 “几何信息” 转换为 “像素”
绘制是根据布局结果,将元素的样式(颜色、阴影、背景等)绘制到屏幕上:
- 过程:按渲染树顺序,为每个元素绘制边框、背景、文本、阴影等;
- 触发因素:样式变化但不影响布局(如
color、background-color); - 优化:将频繁绘制的元素放入 “合成层”(如
transform: translateZ(0)),避免影响其他元素。
6. 合成(Composite):合并 “图层” 并显示
现代浏览器会将页面分为多个 “图层”(如视频层、图片层、文字层),合成阶段将这些图层合并为最终画面并显示在屏幕上:
- 优点:图层间独立绘制,某一图层变化时只需重绘该图层,再重新合成(性能优于整体重绘);
- 常见图层:
<video>、<canvas>、设置了opacity < 1或transform的元素。
7. 渲染阻塞与优化
- JS 阻塞渲染:
<script>默认阻塞 HTML 解析和渲染,可通过defer(延迟执行,不阻塞 HTML 解析,DOM 加载完成后执行)或async(异步执行,下载完成后立即执行,不保证顺序)优化; - CSS 阻塞渲染:CSSOM 未构建完成时,浏览器不会进行布局和绘制,可通过 “内联关键 CSS”(将首屏必要 CSS 嵌入 HTML)、“异步加载非关键 CSS”(如
media="print")优化; - 回流与重绘优化:避免频繁修改布局属性(如
offsetWidth),尽量使用transform和opacity(仅触发合成,不触发回流 / 重绘)。
小结:页面渲染是 “解析→构建→计算→绘制” 的流水线,每个环节都可能成为性能瓶颈。理解渲染机制,是前端性能优化的核心。
十、关闭 TCP 连接:四次挥手的 “优雅告别”
页面渲染完成后,若不再需要通信(如用户关闭页面),TCP 连接会通过 “四次挥手” 关闭,释放资源。
1. 四次挥手的过程
以 “客户端主动关闭连接” 为例:
(1)第一次挥手(客户端→服务器):“我要关闭连接了”
客户端发送FIN 报文(结束报文段),标志位FIN=1,序列号为u(当前发送序列号),表示 “客户端不再发送数据”。
(2)第二次挥手(服务器→客户端):“我知道了,等我处理完剩余数据”
服务器返回ACK 报文,标志位ACK=1,确认号u+1,表示 “已收到关闭请求”。此时服务器仍可向客户端发送数据(半关闭状态)。
(3)第三次挥手(服务器→客户端):“我也准备关闭了”
服务器处理完剩余数据后,发送FIN 报文,标志位FIN=1,序列号为v,表示 “服务器不再发送数据”。
(4)第四次挥手(客户端→服务器):“我知道了,关闭吧”
客户端返回ACK 报文,标志位ACK=1,确认号v+1,表示 “已收到服务器的关闭请求”。服务器收到后关闭连接,客户端等待 2MSL(最长报文段寿命,约 1-4 分钟)后关闭连接(确保服务器收到确认)。
2. 为什么需要四次挥手?
因为 TCP 连接是 “全双工”(双方可同时发送数据),关闭连接时需要双方分别确认 “自己的发送端已关闭”:
- 客户端的 FIN 表示 “客户端→服务器” 方向的连接关闭;
- 服务器的 FIN 表示 “服务器→客户端” 方向的连接关闭;
- 四次挥手确保双方都完成数据发送,避免数据丢失。
小结:四次挥手是 TCP 连接的 “优雅结束” 机制,通过四次报文交换,确保双方都已完成数据传输,安全释放资源。
十一、额外环节:缓存机制与性能优化
在上述流程中,浏览器和服务器会通过缓存机制减少重复请求,提升页面加载速度。缓存是前端性能优化的核心手段,分为 “强缓存” 和 “协商缓存”。
1. 强缓存:直接从本地读取,不发请求
若资源命中强缓存,浏览器直接从本地缓存读取,不向服务器发送请求。控制强缓存的响应头:
Cache-Control: max-age=3600:资源有效期为 3600 秒(1 小时),从请求成功时间开始计算;Expires: Wed, 18 Aug 2024 12:00:00 GMT:资源过期时间(绝对时间),优先级低于Cache-Control。
适用场景:静态资源(如 CSS、JS、图片),且内容不常变化。
2. 协商缓存:询问服务器是否需更新
若强缓存过期,浏览器会向服务器发送请求,询问资源是否更新:
- 客户端发送
If-Modified-Since: 上次修改时间或If-None-Match: 资源ETag; - 服务器对比后,若资源未更新,返回
304 Not Modified(无需返回响应体,客户端使用本地缓存);若已更新,返回200 OK和新资源。
控制协商缓存的响应头:
Last-Modified: 资源最后修改时间;ETag: 资源唯一标识(如哈希值),优先级高于Last-Modified(能识别内容变化,即使修改时间不变)。
3. CDN 的作用:就近获取静态资源
CDN(Content Delivery Network)是分布在全球的缓存服务器网络,专门用于加速静态资源(CSS、JS、图片、视频)的访问:
- 原理:用户请求静态资源时,DNS 会将域名解析到最近的 CDN 节点,若节点缓存了资源,则直接返回;否则 CDN 节点向源服务器请求资源,缓存后再返回;
- 优点:减少源服务器压力,降低网络延迟(用户访问就近节点);
- 场景:大型网站的静态资源几乎都通过 CDN 分发(如淘宝的
g.alicdn.com,百度的ss0.bdstatic.com)。 小结:缓存机制通过 “本地复用” 和 “就近访问” 减少网络请求,是提升页面加载速度的关键。合理配置缓存策略,可显著降低服务器压力和用户等待时间。
总结:从 URL 到页面的完整链条
输入 URL 到页面显示的全过程,是计算机网络、操作系统、浏览器内核协同工作的缩影,可归纳为 11 个核心步骤:
- URL 解析:补全协议、拆分结构,生成标准化地址;
- DNS 解析:通过本地缓存→系统缓存→hosts→递归服务器→根服务器→顶级服务器→权威服务器,获取 IP;
- 协议判断:区分 HTTP/HTTPS,决定是否需要 TLS 握手;
- TCP 三次握手:建立可靠的传输连接;
- TLS 握手(HTTPS) :协商加密算法、交换密钥,确保数据安全;
- 发送 HTTP 请求:构建请求行、请求头、请求体,传递客户端需求;
- 服务器处理:负载均衡→路由匹配→业务逻辑→生成响应;
- 接收响应:处理状态码、响应头、响应体,获取服务器数据;
- 页面渲染:解析 HTML 构建 DOM→解析 CSS 构建 CSSOM→生成渲染树→布局→绘制→合成;
- TCP 四次挥手:关闭连接,释放资源;
- 缓存优化:通过强缓存、协商缓存、CDN 减少重复请求。
每个步骤都包含大量底层细节(如三次握手的序列号、TLS 的密钥交换、渲染的回流重绘),这些细节不仅是面试高频考点,更是理解 “前端性能优化”“网络安全” 的基础。