← 首页·文章列表

从 URL 回车到页面显示

“输入 URL 回车后,页面是怎么显示出来的?” —— 它能串联起计算机网络五层模型的所有核心知识点。本文会按照 应用层→传输层→网络层→数据链路层→物理层 的顺序,把每个环节掰开揉碎讲清楚,保证新手看完就能吃透。

首先我们过一下完整流程框架:

  1. 浏览器输入 URL 并回车
  2. DNS 解析:把域名翻译成服务器的 IP 地址
  3. 建立 TCP 连接:三次握手搞定可靠传输通道
  4. 发送 HTTP/HTTPS 请求:向服务器要网页资源
  5. 服务器处理请求并返回响应:把 HTML 等数据发回浏览器
  6. 浏览器解析渲染页面:加载 HTML、CSS、JS、图片等资源
  7. 关闭 TCP 连接:四次挥手断开通道

下面我们针对每个环节,做详细扩展。

一、 应用层:一切的起点 ——URL 解析与 DNS 域名解析

应用层是直接和用户 “打交道” 的层级,我们输入 URL、解析域名、发送请求的操作,都发生在这一层。

1. 第一步:浏览器解析 URL(Uniform Resource Locators 统一资源定位器)

当你在浏览器地址栏输入 https://www.example.com:8080/path/to/index.html?name=test#top 并回车时,浏览器做的第一件事,就是拆解 URL 的每一部分,搞清楚 “要去哪里、要拿什么、用什么方式拿”。

我们以这个完整 URL 为例,拆解它的 6 个核心组成部分,每个部分的作用和细节如下:

组成部分 示例内容 核心作用 细节
协议部分 https:// 规定浏览器和服务器的通信规则 常见协议:

1. http://:超文本传输协议,明文传输,端口默认 80

2. https://:HTTP+SSL/TLS,加密传输更安全,端口默认 443

3. 其他:ftp://(文件传输)、file://(本地文件)
域名部分 www.example.com 服务器的 “可读名字”,对应唯一 IP 域名≠IP:域名是为了方便人记忆,IP 才是服务器在网络中的真实地址

也可以直接输入 IP 访问,比如 http://127.0.0.1:8080(本地服务器)
端口部分 :8080 标记服务器上的 “具体服务入口” 1. 端口范围 0-65535,0-1023 是系统保留端口(如 80、443)

2. 省略时用默认端口:HTTP 默认 80,HTTPS 默认 443

3. 作用:一台服务器可以开多个端口,提供不同服务(如 8080 跑 Java Web,3306 跑 MySQL)
资源路径部分 /path/to/index.html 服务器上的具体文件位置 1. 以/开头,对应服务器的 “资源根目录”

2. 现在很多路径是虚拟路径:不是服务器上真实的文件位置,而是后端框架(如 Spring Boot)映射的接口地址
参数部分 ?name=test 浏览器传给服务器的额外数据 1. 格式:?key1=value1&key2=value2,多个参数用&分隔

2. 特点:参数会暴露在地址栏,长度有限制(不同浏览器不一样),适合传递少量非敏感数据

3. 注意:如果参数有中文,会自动进行 URL 编码(如 “张三”→%E5%BC%A0%E4%B8%89)
锚点部分 #top 页面内的定位标记 注意::

1. 锚点不会发送给服务器!浏览器解析到#时,只会在本地页面滚动到对应 id 的位置(如<div id="top"></div>)

2. 作用:实现页面内的快速跳转,比如长文档的目录链接

拆解完 URL 后,浏览器确认了协议是 HTTPS、目标服务器是www.example.com、端口是 8080,接下来就要解决核心问题:www.example.com对应的 IP 地址是什么? —— 这就是 DNS 解析的工作。

2. 第二步:DNS 域名解析 —— 把 “名字” 翻译成 “地址”

DNS(Domain Name System 域名系统)的作用,相当于互联网的 “电话簿”—— 通过域名查 IP,或者通过 IP 查域名(反向解析)。

我们用 “查字典” 的比喻,一步步讲清楚浏览器是怎么找到 IP 的,全程遵循 “先本地,后远程” 的原则,优先查缓存,提高效率。

(1) 浏览器本地缓存查询

浏览器会先查自己的DNS 缓存—— 这是浏览器为了加快访问速度,保存的最近访问过的域名 - IP 映射记录,有过期时间(TTL)。

(2) 操作系统本地缓存查询

如果浏览器缓存里没有,就会去查操作系统的本地 DNS 缓存。

(3) 本地 Hosts 文件查询

如果系统缓存也没有,浏览器会去读本地 Hosts 文件—— 这是一个没有扩展名的文本文件,手动配置域名和 IP 的映射。

(4) 向本地 DNS 服务器发起请求(递归查询)

如果前面三步都没找到,真正的 “远程查询” 才开始。浏览器会向本地 DNS 服务器(一般是你的路由器,或者运营商提供的 DNS 服务器,比如电信的 114.114.114.114)发起请求。

这个过程是递归查询:你只需要告诉本地 DNS 服务器 “我要查www.example.com的 IP”,剩下的事不用管,它会帮你搞定,查不到就返回错误。

(5) 本地 DNS 服务器的迭代查询(核心步骤)

本地 DNS 服务器拿到请求后,如果自己的缓存里没有,就会进行迭代查询,相当于 “逐级问路”,从根 DNS 服务器开始,一级一级往下查:

  1. 问根 DNS 服务器:“请问www.example.com的 IP 在哪里?”

    根 DNS 服务器是互联网的最高级 DNS 服务器,全球只有 13 台(实际上已经是200多台了),它不知道具体 IP,但会告诉你:“.com 域名的管理服务器在这,你去问它。”

  2. 问顶级域名服务器(.com 服务器):顶级域名服务器管理.com、.cn、.org 等后缀的域名,它会告诉你:“example.com的域名服务器在这,你去问它。”

  3. 问权威 DNS 服务器(example.com服务器):这是example.com域名的专属 DNS 服务器,记录了这个域名的所有解析记录(A 记录:域名→IPv4;AAAA 记录:域名→IPv6)。它会直接返回 www.example.com 对应的 IP 地址。

(6) 结果返回

权威 DNS 服务器把 IP 返回给本地 DNS 服务器,本地 DNS 服务器缓存这个结果,再把 IP 返回给浏览器。

到这里,应用层的核心工作就完成了 —— 浏览器拿到了服务器的IP 地址和端口号,接下来要进入传输层,建立可靠的连接。

二、 传输层:建立 TCP 连接 —— 三次握手的 “可靠约定”

应用层的 HTTP/HTTPS 协议,必须基于 TCP 协议来传输数据 —— 因为 HTTP 本身是 “无连接、无状态” 的,而 TCP 的 “面向连接、可靠传输” 特性,能保证数据不会丢、不会乱序。

传输层的核心工作,就是通过三次握手,在浏览器(客户端)和服务器之间建立一条稳定的 “数据传输通道”。

我们先明确两个核心概念:

TCP 三次握手的详细过程

你可以把三次握手理解为客户端和服务器的 “通话约定”:

握手次数 发起方 发送的内容 核心作用 通俗理解
第一次握手 客户端→服务器 SYN=1,seq=x(随机生成的初始序列号) 客户端:“我想和你建立连接,我的初始序列号是 x,你收到了吗?” “喂,你在吗?我想和你说话。”
第二次握手 服务器→客户端 SYN=1,ACK=1,seq=y,ack=x+1 服务器:“我收到了(ack=x+1),我也想和你建立连接,我的初始序列号是 y,你收到了吗?” “我在,我也想和你说话,你听到我的回应了吗?”
第三次握手 客户端→服务器 ACK=1,seq=x+1,ack=y+1 客户端:“我收到了(ack=y+1),我们的连接可以建立了!” “我听到了,那我们开始聊天吧!”

新手必知的三次握手关键点

  1. 为什么需要三次握手? —— 防止 “失效的连接请求” 占用服务器资源。

    比如客户端发的连接请求因为网络延迟,很久才到服务器,服务器回了确认,但客户端已经超时了,不会处理这个确认。如果只有两次握手,服务器会以为连接建立了,一直等客户端发数据,浪费资源;三次握手的话,客户端没发第三次确认,服务器就知道连接没建立成功。

  2. 三次握手成功后:客户端和服务器都进入ESTABLISHED(已建立连接)状态,这条通道是全双工的 —— 双方可以同时发数据。

补充:HTTPS 的额外步骤 ——SSL/TLS 握手

如果是 HTTPS 协议,在 TCP 三次握手之后,还会多一步SSL/TLS 握手,目的是建立加密通道,防止数据被窃听、篡改:

  1. 客户端向服务器发送支持的 SSL/TLS 版本、加密套件列表。
  2. 服务器选择加密套件,返回数字证书(包含服务器公钥)。
  3. 客户端验证证书合法性(比如是否由可信机构颁发)。
  4. 客户端生成一个随机的 “会话密钥”,用服务器公钥加密后发给服务器。
  5. 服务器用自己的私钥解密,拿到会话密钥。
  6. 双方用会话密钥进行对称加密通信(对称加密速度快,适合传输大量数据)。

到这里,传输层的连接就完全建立好了,接下来应用层的 HTTP 请求,就可以在这条可靠的通道里传输了。

三、 应用层再发力:发送 HTTP 请求 & 服务器处理并返回响应

TCP 连接建立后,浏览器就可以向服务器发送HTTP 请求报文,索要网页资源了。这一步依然属于应用层,是 HTTP 协议的核心交互过程。

1. HTTP 请求报文的结构

HTTP 请求报文由请求行、请求头、空行、请求体四部分组成,我们用一个实际的 GET 请求例子来拆解:

GET /path/to/index.html?name=test HTTP/1.1  (请求行)
Host: www.example.com:8080                 (请求头)
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0
Accept: text/html,application/xhtml+xml
Connection: keep-alive

                                           (空行)
                                           (请求体:GET请求一般没有请求体)

2. 服务器处理请求的过程

服务器收到 HTTP 请求后,会按照以下步骤处理:

  1. 解析请求报文:Web 服务器(如 Nginx、Tomcat)先解析请求行、请求头,拿到请求方法、资源路径、参数等信息。
  2. 路由匹配:如果是动态网页(如 Java Web、Spring Boot 项目),后端框架会根据请求路径,匹配对应的控制器方法(如@RequestMapping("/path/to/index"))。
  3. 业务逻辑处理:控制器方法执行业务逻辑(如查询数据库、调用其他接口)。
  4. 生成响应数据:业务逻辑处理完后,生成要返回的内容 —— 可以是静态 HTML 文件,也可以是动态生成的 JSON 数据。
  5. 封装 HTTP 响应报文:把响应内容封装成 HTTP 响应报文,返回给浏览器。

3. HTTP 响应报文的结构(和请求报文对应)

HTTP 响应报文由状态行、响应头、空行、响应体四部分组成,例子如下:

HTTP/1.1 200 OK  (状态行)
Server: Nginx/1.21.6  (响应头)
Content-Type: text/html; charset=utf-8
Content-Length: 1024
Connection: keep-alive

                     (空行)
<!DOCTYPE html>      (响应体:HTML代码)
<html>
<head><title>Example</title></head>
<body><h1>Hello World</h1></body>
</html>

四、 网络层 + 数据链路层 + 物理层:数据的 “快递运输” 过程

前面我们讲了应用层和传输层的交互,但数据从客户端到服务器,不是直接飞过去的 —— 需要经过网络层、数据链路层、物理层的层层封装和传输,这个过程就像寄快递:

1. 数据封装:从应用层到物理层(层层打包)

当浏览器要发送 HTTP 请求报文时,数据会从上层到下层,每一层都加上自己的 “头部信息”,这个过程叫封装:

  1. 应用层:生成 HTTP 请求报文(数据)
  2. 传输层:加上 TCP 头部(包含源端口、目的端口、seq、ack),变成TCP 报文段
  3. 网络层:加上 IP 头部(包含源 IP、目的 IP),变成IP 数据报
  4. 数据链路层:加上 MAC 头部(包含源 MAC 地址、目的 MAC 地址)和尾部(校验码),变成数据帧
  5. 物理层:把数据帧转换成二进制比特流(0 和 1),通过网线、WiFi 等物理介质传输

2. 路由转发:IP 数据报的 “寻路之旅”(网络层核心)

网络层的核心是IP 协议,负责将 IP 数据报从客户端 “送” 到服务器,关键是路由转发:

3. 数据解封装:从物理层到应用层(层层拆包)

当数据帧到达服务器所在的物理网卡后,会从下层到上层,每一层都拆掉自己的头部信息,这个过程叫解封装:

  1. 物理层:把比特流转换成数据帧,传给数据链路层
  2. 数据链路层:拆掉 MAC 头部和尾部,校验数据是否正确,把 IP 数据报传给网络层
  3. 网络层:拆掉 IP 头部,把 TCP 报文段传给传输层
  4. 传输层:拆掉 TCP 头部,根据端口号,把 HTTP 请求报文传给应用层的 Web 服务器
  5. 应用层:Web 服务器解析 HTTP 请求报文,开始处理请求

总结:数据从客户端到服务器,经历了 “封装→传输→解封装” 的过程;五层模型的每一层,都只关心自己的头部信息,上层的数据对它来说就是 “透明的负载”。

五、 浏览器的 “重头戏”:解析响应 & 渲染页面

浏览器收到服务器返回的 HTTP 响应后,如果响应体是 HTML 代码,就会进入解析和渲染阶段—— 这是前端的核心工作,也是页面最终显示的关键。

这个阶段会触发多次 HTTP 请求,因为 HTML 页面里通常包含很多 “子资源”(CSS、JS、图片、字体等),浏览器需要逐个请求这些资源,才能完整显示页面。

我们把这个过程拆成6 个核心步骤:

1. 解析 HTML,生成 DOM 树(Document Object Model 文档对象模型)

浏览器会逐行解析 HTML 代码,把每个标签(如<html>、<body>、<h1>)转换成 DOM 树的一个节点,节点包含标签的属性、文本内容等信息。

2. 解析 CSS,生成 CSSOM 树(CSS Object Model CSS 对象模型)

浏览器会解析 HTML 中的<style>标签,以及<link rel="stylesheet">引用的外部 CSS 文件,生成 CSSOM 树 ——CSSOM 树记录了所有样式规则(如h1 { color: red; })。

3. 结合 DOM 树和 CSSOM 树,生成渲染树(Render Tree)

渲染树是 ** 只包含 “可见元素”** 的树形结构:

4. 布局(Layout):计算元素的位置和大小(回流 / 重排)

浏览器会根据渲染树,计算每个元素的几何属性:

5. 绘制(Painting):把元素画到屏幕上(重绘)

布局完成后,浏览器会遍历渲染树,把每个元素的视觉属性(如颜色、背景、边框)画到屏幕上,这个过程叫绘制(Painting)。

6. 合成(Compositing):分层显示,提升性能

现代浏览器会把页面分成多个图层(比如<video>、<canvas>、transform属性的元素会单独分层),每个图层独立绘制,最后合成到一起显示在屏幕上。

7. 加载子资源,重复请求 - 渲染过程

在解析 HTML 的过程中,浏览器遇到<img>、<link>、<script>等标签时,会触发新的 HTTP 请求:

直到所有子资源都加载完成,页面才会完全显示在浏览器窗口中。

六、 传输层:关闭 TCP 连接 —— 四次挥手的 “告别流程”

当页面加载完成后,浏览器和服务器就可以关闭 TCP 连接了。由于 TCP 是全双工连接,关闭连接需要四次挥手,比三次握手多一次 —— 因为双方都需要单独告诉对方 “我没有数据要发了”。

TCP 四次挥手的详细过程

把四次挥手理解为客户端和服务器的 “告别对话”:

挥手次数 发起方 发送的内容 核心作用 通俗理解
第一次挥手 客户端→服务器 FIN=1,seq=u 客户端:“我没有数据要发了,我的序列号是 u,你收到了吗?” “我说完了,轮到你了。”
第二次挥手 服务器→客户端 ACK=1,seq=v,ack=u+1 服务器:“我收到了(ack=u+1),我还有点数据没发完,你等我一下。” “我知道你说完了,我还有点话要说。”
第三次挥手 服务器→客户端 FIN=1,ACK=1,seq=w,ack=u+1 服务器:“我也没有数据要发了,我的序列号是 w,你收到了吗?” “我说完了,我们可以结束了。”
第四次挥手 客户端→服务器 ACK=1,seq=u+1,ack=w+1 客户端:“我收到了(ack=w+1),请等我 2MSL 时间,我确认你收到了我的确认,我们的连接就关闭了。” “我知道你说完了,我等一会儿,确认你收到消息,就挂了。”

四次挥手关键点

  1. 为什么需要四次挥手? —— TCP 是全双工连接,双方都需要独立关闭发送通道。

    第一次和第二次挥手,关闭客户端→服务器的通道;第三次和第四次挥手,关闭服务器→客户端的通道。

  2. 2MSL 等待时间:客户端发完第四次挥手的确认后,会等待 2 倍的 MSL(Maximum Segment Lifetime,报文段最大生存时间),再关闭连接。

    目的是:确保服务器收到第四次确认;如果服务器没收到,会重发第三次挥手的 FIN 报文,客户端在 2MSL 时间内收到后,会重新发第四次确认。

  3. 特殊情况:Connection: keep-alive:如果 HTTP 请求头里设置了Connection: keep-alive,TCP 连接不会立即关闭,会被复用,用来传输后续的子资源请求(如 CSS、JS),减少三次握手的开销。

七、 总结:从 URL 回车到页面显示的完整流程图(新手必背)

我们把所有步骤串起来,形成一个完整的闭环:

输入URL回车
    ↓
浏览器解析URL(协议、域名、端口、路径)
    ↓
DNS解析(本地缓存→Hosts→本地DNS→根DNS→顶级DNS→权威DNS)→ 拿到IP地址
    ↓
传输层:TCP三次握手(客户端→SYN → 服务器→SYN+ACK → 客户端→ACK)→ 建立连接
    ↓
(HTTPS专属)SSL/TLS握手 → 建立加密通道
    ↓
应用层:浏览器发送HTTP请求报文(请求行+请求头+空行+请求体)
    ↓
数据封装(应用层→传输层→网络层→数据链路层→物理层)
    ↓
网络层:IP路由转发 → 数据通过物理介质传输到服务器
    ↓
数据解封装(物理层→数据链路层→网络层→传输层→应用层)
    ↓
服务器解析HTTP请求 → 处理业务逻辑 → 返回HTTP响应报文(状态行+响应头+空行+响应体)
    ↓
浏览器接收响应 → 解析HTML生成DOM树 → 解析CSS生成CSSOM树 → 合成渲染树
    ↓
布局(计算位置大小)→ 绘制(画到屏幕)→ 合成(分层显示)
    ↓
请求HTML中的子资源(CSS、JS、图片等)→ 重复上述流程
    ↓
页面完全显示 → 传输层:TCP四次挥手 → 关闭连接