目录
打开一个网页时发生了什么?网络通信入门
从在浏览器里输入网址到页面出现,背后依次发生了 DNS 解析、TCP 三次握手、TLS 握手和 HTTP 请求响应。本文用一张时序图把每一步做了什么讲清楚。
网络原理系列:① 打开一个网页时发生了什么 → ② 网络分层模型 → ③ 常见网络协议 → ④ 代理是什么 → ⑤ 加密隧道是什么 → ⑥ 加密隧道与代理的区别 → ⑦ HTTPS 加密了什么 → ⑧ 系统代理与 TUN 模式 → ⑨ 分流是什么 → ⑩ DNS 污染与泄漏 → ⑪ 晚高峰为什么变慢 → ⑫ 延迟、丢包与带宽
在浏览器地址栏输入一个网址、按下回车,到页面完整出现,通常不到一秒。这一秒里,浏览器依次做了四件事:用 DNS 把域名换成 IP 地址 → 用 TCP 三次握手和服务器建立连接 → 用 TLS 握手商量好加密方式 → 用 HTTP 发出请求、取回网页。下面一步步拆开来看,文末用一张时序图把整个过程串起来。
先从寄信说起
上网传递信息,和寄一封重要的信非常像。想象你要给远方的朋友寄一封信,并等他回信:
- 查地址:你只记得朋友的名字,得先翻地址簿,查到他家的具体地址;
- 打电话确认:寄之前先打个电话,「我要给你寄信了,你在家吗?」「在,寄吧!」——确认双方都联系得上;
- 上锁:信里有隐私,你把信锁进一个箱子,和朋友约定好只有你们俩能打开的钥匙;
- 邮局分拣:箱子交给邮政系统,一路经过好几个邮局,每个邮局只看地址,决定下一站送到哪里;
- 对方收信:朋友收到箱子,用钥匙打开,读到你的请求;
- 回信:朋友按原路把回信寄回来,你拆开就看到了想要的内容。
- ① 查地址DNS 解析:把域名换成 IP 地址
- ② 打电话确认TCP 三次握手:确认双方都能收发
- ③ 上锁、约定钥匙TLS 握手:协商加密,确认对方身份
- ④ 邮局分拣路由:每台路由器按目标 IP 转发
- ⑤ 对方收信HTTP 请求:「请把首页给我」
- ⑥ 寄回回信HTTP 响应:网页内容送回浏览器
打开网页的过程几乎一模一样,只是每一步都换成了网络协议,而且整个过程通常不到一秒:
| 寄信 | 上网 | 本文对应 |
|---|---|---|
| 朋友的名字 | 域名(如 example.com) | 第一步 |
| 查地址簿,得到家庭地址 | DNS 解析,得到 IP 地址 | 第一步 |
| 地址里的门牌号 + 房间号 | IP 地址 + 端口号 | 下一节 |
| 打电话确认对方在家 | TCP 三次握手 | 第二步 |
| 把信锁进箱子、约定钥匙 | TLS 握手,协商加密 | 第三步 |
| 一路经过的邮局 | 路由器 | 「数据包怎么跨过几十个路由器」 |
| 信的内容和回信 | HTTP 请求和响应 | 第四步 |
先认识两个概念:IP 地址和端口
互联网上的每一台设备都有一个 IP 地址,就像门牌号,数据包要靠它才能被送到正确的设备。光有门牌号还不够,一台服务器上可能同时运行着网站、邮件等很多程序,所以还需要 端口号 指明「交给这台设备上的哪个程序」,就像同一栋楼里的房间号:
- 网站用的 HTTPS 默认是 443 端口,老式不加密的 HTTP 是 80 端口;
- 你在地址栏里一般看不到端口号,是因为浏览器自动使用了默认端口。
所以,访问一个网站,本质上就是和「某个 IP 地址的 443 端口」进行通信。问题是:我们记住的是 example.com 这样的域名,而不是一串数字。这就需要第一步。
第一步:DNS 解析,把域名换成 IP 地址
DNS(域名系统)相当于互联网的「电话簿」,负责把域名翻译成 IP 地址。浏览器会按顺序找答案,找到就停:
- 浏览器自己的缓存:最近访问过的域名,直接用;
- 操作系统的缓存和 hosts 文件;
- DNS 服务器:通常是运营商或路由器提供的,也可以是公共 DNS。如果它也不知道,会替你逐级去问:先问根域名服务器「.com 归谁管」,再问 .com 的服务器「example.com 归谁管」,最后问 example.com 的权威服务器拿到真正的 IP 地址。
查到的结果会被缓存一段时间(由网站设置的 TTL 决定),所以同一个网站第二次打开时,往往就不用再查了。DNS 逐级查询的细节见 常见网络协议。
第二步:TCP 三次握手,确认双方都能收发
拿到 IP 地址后,浏览器要先和服务器「打个招呼」,建立一条 TCP 连接。TCP 负责保证数据完整、按顺序地送达,丢了会重传。建立连接需要来回三次,所以叫「三次握手」:
- 浏览器:「我想和你建立连接」(SYN);
- 服务器:「收到,我也准备好了」(SYN-ACK);
- 浏览器:「好,那我们开始吧」(ACK)。
为什么要三次?因为双方都需要确认自己发的对方能收到、对方发的自己也能收到。少一次,总有一方无法确认。
第三步:TLS 握手,商量好加密方式
网址以 https 开头时,在正式传数据之前,还要做一次 TLS 握手,目的是两件事:确认对方真的是这个网站,以及商量出一把只有双方知道的密钥。以现在主流的 TLS 1.3 为例:
- 浏览器发出 ClientHello:我支持哪些加密算法,并附上自己的密钥参数;
- 服务器回复 ServerHello:选定加密算法、附上它的密钥参数,同时出示证书;
- 浏览器验证证书:证书是不是由可信的机构签发、有没有过期、上面的域名对不对。验证通过后,双方各自用交换的参数算出同一把会话密钥(密钥本身从来没有在网络上传输过);
- 双方互发 Finished,确认握手过程没有被篡改。
从这以后,双方的通信内容全部用这把会话密钥加密。
第四步:HTTP 请求与响应,取回网页
连接和加密都准备好了,浏览器终于可以说出真正的目的:发出一个 HTTP 请求,例如「GET /,请把首页给我」,同时附上浏览器类型、语言、Cookie 等信息。服务器处理后返回 HTTP 响应:一个状态码(200 表示成功,404 表示找不到,500 表示服务器出错)和网页的 HTML 内容。
浏览器开始解析 HTML,发现里面还引用了图片、样式表、脚本,于是继续发出更多请求。一个普通网页往往需要几十上百个请求,它们会复用已经建立的连接,在 HTTP/2、HTTP/3 下还能同时并行传输。全部取回后,浏览器把它们组合起来,渲染出你看到的页面。
数据包是怎么跨过几十个路由器的?
上面每一步的数据,都被切成一个个数据包发出去。你的电脑和服务器之间并没有一根直达的网线,数据包要经过家里的路由器、运营商的机房、跨城甚至跨国的骨干网,中间往往有十几到几十台路由器。
每台路由器只做一件事:看数据包上的目标 IP 地址,查自己的路由表,把它转发给「离目标更近的下一站」。就像快递在每个分拣中心只决定下一站发往哪里,而不需要知道完整路线。
想亲眼看看这条路径,可以用系统自带的命令:
# macOS / Linux
traceroute example.com
# Windows(在命令提示符里运行)
tracert example.com
输出的每一行就是路上的一台路由器,后面的毫秒数是数据包到达那里再返回所需的时间。数值在某一跳突然变大,往往说明那一段线路比较拥堵或距离很远(比如跨海光缆)。
一张图总结全过程
下面把四个步骤放在同一张时序图里。左边是你的浏览器,中间是 DNS 服务器,右边是网站服务器;从上往下是时间顺序,粗线表示已经加密的数据:
| 步骤 | 发生了什么 | 为什么需要 |
|---|---|---|
| ① 查询 IP | 浏览器问 DNS 服务器:这个域名的 IP 是多少 | 网络只认 IP 地址,不认域名 |
| ② 返回 IP | DNS 服务器给出 IP 地址(必要时它会逐级去问根、顶级、权威服务器) | 拿到目的地的「门牌号」 |
| ③ SYN | 浏览器向网站的 443 端口发起连接请求 | 开始 TCP 三次握手 |
| ④ SYN-ACK | 服务器确认收到,并表示自己也准备好了 | 证明「浏览器 → 服务器」这个方向是通的 |
| ⑤ ACK | 浏览器确认收到服务器的回复 | 证明「服务器 → 浏览器」这个方向也是通的,连接建立 |
| ⑥ ClientHello | 浏览器列出支持的加密算法,并发出自己的密钥参数 | 开始 TLS 握手 |
| ⑦ ServerHello + 证书 | 服务器选定算法、发出它的密钥参数和证书 | 让浏览器能确认网站身份、算出密钥 |
| ⑧ 验证证书、算出密钥 | 浏览器检查证书是否可信、是否匹配域名,并算出会话密钥 | 防止连到冒充的网站;密钥不经网络传输 |
| ⑨ Finished | 浏览器确认握手完成(服务器的 Finished 已随 ⑦ 一起发出) | 确认整个握手过程没有被篡改 |
| ⑩ GET / | 浏览器发出加密的 HTTP 请求 | 真正索取网页 |
| ⑪ 200 OK + 网页 | 服务器返回加密的网页内容 | 浏览器拿到 HTML |
| ⑫ 渲染页面 | 浏览器解析 HTML,继续请求图片、样式、脚本,最后渲染出页面 | 你看到完整的网页 |
在正常网络下,①–⑨ 一共只需要几十到几百毫秒;如果服务器在海外,每一次来回都要跨越大洋,握手阶段就会明显变慢,这也是访问海外网站「打开慢」的主要原因之一。
相关阅读
常见问题
为什么第二次打开同一个网站更快?
很多步骤被省掉了:域名对应的 IP 已经缓存,不用再查 DNS;浏览器会复用之前建立的连接,TLS 也可以用「会话恢复」跳过大部分握手;图片、脚本等文件本身也被浏览器缓存在本地。
网址前面的 http 和 https 有什么区别?
https 多了 TLS 加密这一步。用 http 时,网页内容在网络上以明文传输,沿途的人都能看到甚至篡改;用 https 时,内容在你和网站之间是加密的。现在绝大多数网站都已经使用 https。
网页一直在转圈,怎么知道卡在哪一步?
在浏览器里按 F12 打开开发者工具,切到「网络」(Network)面板刷新页面,点开第一个请求看「时间」(Timing):DNS Lookup、Initial connection、SSL、Waiting for server response 分别对应本文的 DNS、TCP、TLS 和 HTTP,哪一段特别长,问题就在哪一步。