LV055-浏览器输入到页面显示的全过程
一、 拆解输入:这不是一个网址
在浏览器地址栏敲下"github是什么"再按下 Enter——很多人以为这会直接连上 GitHub,其实第一件事就错了:这不是 URL,是一串搜索关键词。
1. 地址栏的两个身份
现代浏览器的地址栏(Chrome 里叫 omnibox)承担两种职责:输入合法网址就当 URL 直接访问;输入的不是网址,就转交给默认搜索引擎。浏览器判断的依据大致是:
(1)字符串里有协议头(https://)、有合法域名(含 . 且各段合法)、或以 localhost / IP 地址开头 → 当作 URL 处理。
(2)含空格、纯中文、或者"点号分段"不满足域名字符规则 → 当作搜索词。
"github是什么"含中文、没有点号,显然落在第二类。浏览器会把它拼进搜索引擎的搜索模板,比如百度是 https://www.baidu.com/s?wd=<关键词>。
2. 搜索引擎拿到了什么
关键词不会原样出现在 URL 里。浏览器先对它做 URL 编码(百分号编码):"github是什么" 变成 github%E6%98%AF%E4%BB%80%E4%B9%88——"是"和"什"、"么"三个汉字按 UTF-8 各占 3 字节,每字节写成 %XX。所以浏览器真正发起的第一个请求是:
https://www.baidu.com/s?wd=github%E6%98%AF%E4%BB%80%E4%B9%88从按下 Enter 到这一步只过了几毫秒,网络之旅尚未开始,但输入已经被"翻译"成了网络能理解的形式。整趟旅程先看总览:
二、 第一步:把关键词交给搜索引擎
1. DNS:查出搜索服务器的 IP
URL 里的 www.baidu.com 只是给人看的名字,发包前必须先换成 IP 地址。浏览器按这个顺序查 DNS 缓存:
(1)浏览器自身缓存;
(2)操作系统缓存与 hosts 文件;
(3)本机配置的 DNS 服务器(家用网络里通常就是路由器),查不到会递归问根域名服务器、.com 顶级域服务器、baidu.com 权威服务器,最终拿到 IP。
这一步用的是 UDP 53 端口。顺带一提,家庭网络的 IP、子网掩码、DNS 服务器地址多半是开机时 DHCP 自动发下来的,参见 LV040-DHCP与IP地址自动获取。
2. TCP 与 TLS:建立加密通道
拿到 IP 后,浏览器发起 HTTPS 请求,先走 TCP:
(1)与服务器 IP 的 443 端口完成三次握手,建立 TCP 连接(握手细节见 LV035-传输层端口UDP与TCP)。
(2)在这条 TCP 连接上做 TLS 握手:协商加密套件、验证服务器证书、交换密钥,之后的应用数据全部加密传输。这是 URL 能写 https 的原因。
(3)发送 GET /s?wd=github%E6%98%AF... HTTP/1.1,带上 Host、浏览器标识等请求头。
(4)服务器返回 200 OK 和一整页 HTML——搜索结果页的正文就是这串 UTF-8 字节。
如果本机还没学到网关的 MAC 地址,发包前还有一次 ARP 请求打头阵(见 LV030-ARP与MAC地址);包出内网、跨路由的路径选择见 LV015-网关与跨网段通信。
3. 结果页在本地成形
浏览器收到 HTML 后立刻进入渲染流水线(渲染细节统一放在第四章讲),几百毫秒后,你看到了一列搜索结果——其中通常第一条是 GitHub 官网或它的某个中文介绍页。到这里为止,我们还没有碰过 GitHub 一次:搜索是搜索引擎替你完成的,它爬的是早已抓好的网页库。
三、 第二步:点击结果,向 GitHub 发起请求
1. 又一次 DNS,这次查 github.com
点击结果链接,浏览器对 github.com 走一遍同样的 DNS 流程。GitHub 的域名解析通常返回多个 A 记录 / AAAA 记录,配合 CDN,会把用户引导到离自己最近的接入点——这是大厂网站的常规做法。
2. 握手、请求、响应
接下来与搜索那一步完全同构:
(1)TCP 三次握手连上 GitHub 的 443 端口;
(2)TLS 握手验证 github.com 的证书(证书里的域名必须与你访问的一致,否则浏览器报安全警告);
(3)发出 GET / HTTP/1.1;
(4)服务器返回首页 HTML,状态码 200。
一个细节:国内网络环境下,这一步可能失败或超时——表现就是浏览器转圈后报"无法访问此网站"。DNS 正常、握手不通,恰恰说明问题出在 IP 可达性而不是域名解析,这是排查网络问题时的基本判断方法(工具用法见 LV045-网络调试工具与抓包)。
两段请求的完整时序(消息谁先谁后、谁是请求谁是响应)画在一张图里:
3. 首页 HTML 只是个开头
GitHub 首页的 HTML 文档本身不大,但里面引用了数十个静态资源:JavaScript 脚本、样式表、字体、图标、头像图片等,分别挂在 github.githubassets.com、avatars.githubusercontent.com 这些 CDN 域名下。浏览器要再为每个域名做 DNS + 握手 + 请求,这解释了为什么"页面开始显示"和"页面加载完"是两件事。
四、 第三步:浏览器把字节变成画面
网络部分到此结束,剩下的发生在浏览器进程内部——渲染引擎把 HTTP 响应的字节流变成屏幕上的像素。
1. 解析:从 HTML 到 DOM
渲染引擎逐字节读入 HTML,按语法规则解析成一棵 DOM 树(文档对象模型)。解析过程中遇到 <link rel="stylesheet">、<script src>、<img> 等标签,就向对应 URL 发起资源请求——这就是上一节说的"后续资源"。这些请求与主文档的请求并发行进,受浏览器的同域名并发连接数限制。
2. 样式与绘制
CSS 被解析成 CSSOM,与 DOM 合成渲染树;随后浏览器计算每个节点的几何位置(布局 / reflow),再逐层绘制到屏幕上(绘制 / paint)。传统流水线是"布局 → 绘制 → 合成",现代浏览器把页面切成若干图层分别绘制,最后由合成线程合帧,滚动动画因此可以不经过主线程。
3. JavaScript 的位置
<script> 默认会阻塞 HTML 解析——脚本可能修改 DOM,必须先执行完再继续。GitHub 这类现代站点大量依赖 JS:首屏骨架先渲染出来,动态数据(时间线、通知数等)由脚本再发 AJAX / fetch 请求补上。所以你在屏幕上看到"最终页面"之前,背后可能又发生了几十次小请求,只是用户感知不到。
整条渲染流水线跑完,从敲下 Enter 算起通常在数百毫秒到几秒之间,其中网络传输占了绝大部分时间。
五、 全程协议清单
把这次旅程浓缩成一张表,每个环节都能在本目录找到对应的展开篇:
| 环节 | 动作 | 用到的协议 / 机制 | 本目录对应篇 |
|---|---|---|---|
| 判定输入 | 关键词 → 搜索 URL | URL 编码 | —— |
| 找服务器 | 域名 → IP | DNS(UDP 53) | LV040-DHCP(DNS 地址从哪来) |
| 出内网 | IP → MAC | ARP | LV030-ARP与MAC地址 |
| 跨网段 | 逐跳转发 | IP + 路由 | LV015-网关与跨网段通信 |
| 建连接 | 三次握手 | TCP | LV035-传输层端口UDP与TCP |
| 加密 | TLS 握手 | TLS | —— |
| 取数据 | 请求与响应 | HTTP / HTTPS | —— |
| 成画面 | 渲染 | DOM / CSSOM / JS | —— |
未列出的部分(TLS、HTTP 细节、渲染引擎)属于应用层与浏览器专题,超出"网络基础"的边界,这里只给出它们在整个链条中的位置。
这些协议自上而下各占协议栈一层,一层只对上一层负责:
六、 小结与参考资料
1. 本篇小结
- "github是什么"不是 URL,浏览器把它交给默认搜索引擎,先做 URL 编码再发起请求。
- 完整链路是:DNS 查 IP → ARP 找网关 → 路由转发 → TCP 握手 → TLS 握手 → HTTP 请求响应,搜索与点击结果各走一遍。
- 看到页面 ≠ 加载完:HTML 先到先渲染,样式、脚本、图片等资源还在并发请求。
- 渲染引擎把字节变成 DOM、CSSOM、渲染树,最后绘制合帧;JS 会阻塞解析,动态内容靠二次请求补齐。
- 这趟旅程串起了本目录的分层模型、IP、ARP、路由、TCP、DHCP 各篇——网络基础课的终点,就是能对任何一次"上网"说出每一跳发生了什么。
2. 参考资料
- 整体流程的经典综述:What really happens when you navigate to a URL(GitHub 上的开源协作文档)
- 渲染流水线:MDN — Populating the page: how browsers work
- URL 编码标准:RFC 3986 — Uniform Resource Identifier
- 姊妹篇:LV050-一次ping的完整旅程(同一套链路的命令行视角)
本文档由 markdowncli 技能辅助生成