敲下回车后都发生了什么
某天在水群的时候看见了一句话"计网的几层也可以通过输入网址敲击回车后发生了什么串起来",刚好也在补基础,所以就窃取了灵感,学习一下计网的基础知识,顺便水一篇博客
每天我们都无数次通过浏览器这个通向全世界的窗口来上网冲浪,但鲜少有人注意当我们每次在地址栏输入网址,按下enter键后都发生了什么
浏览器解析URL
URL(同意资源定位符)是因特网中的唯一资源的地址。它是浏览器用于检索已发布资源(例如HTML页面,CSS文档,图像等)的关键机制之一。
理论上说,每个有效的 URL 都指向一个唯一的资源。
比如有这样一个URL:
https://www.example.com:443/path/index.html?name=alice#section
它可以拆成:
| 部分 | 含义 |
|---|---|
https | 使用 HTTPS 协议 |
www.example.com | 目标域名 |
443 | 端口号,HTTPS 默认 443 |
/path/index.html | 请求路径 |
?name=alice | 查询参数 |
#section | 页面内片段,不会发送给服务器 |
浏览器首先要弄清楚三件事:
- 用什么协议访问?
- 访问哪个主机?
- 请求哪个资源?
如果没有显式写端口,浏览器会根据协议补默认端口:
| 协议 | 默认端口 |
|---|---|
| HTTP | 80 |
| HTTPS | 443 |
DNS解析
真正的网址看上去并不像你输入到地址栏中的那样美好且容易记忆。它们是特殊的数字,像 192.0.2.172。
这串数字叫做IP地址,它代表的是web上独一无二的位置。然而,它并不容易记忆,不是吗?那就是发明域名系统(DNS)的原因。这个系统使用特殊的服务器将你输入到浏览器(如“mozilla.org”)的网址匹配到网站真实的(IP)地址。
当你输入www.example.com时,浏览器需要先知道这个域名对应哪个IP地址
DNS 查询通常会按下面顺序尝试:
- 浏览器 DNS 缓存
- 操作系统 DNS 缓存
- hosts 文件
- 本地 DNS 服务器
- 根 DNS 服务器
- 顶级域 DNS 服务器,比如
.com - 权威 DNS 服务器
最终得到类似结果:
www.example.com -> 93.184.216.34
这一步主要用到的协议是DNS协议,跑在最顶端的应用层
DNS 一般使用 UDP 53 端口,但在响应过大、区域传输等场景下也可能使用 TCP。
判断目标 IP 在不在同一个网络
拿到 IP 后,主机会判断目标地址是否和自己处于同一个局域网。
假设本机信息如下:
本机 IP:192.168.1.100
子网掩码:255.255.255.0
默认网关:192.168.1.1
目标 IP:93.184.216.34
通过子网掩码判断后,发现目标 IP 不在本地局域网。
于是数据不能直接发给目标服务器,而是先发给默认网关,也就是路由器。
这里涉及几个概念:
| 概念 | 作用 |
|---|---|
| IP 地址 | 标识网络中的主机 |
| 子网掩码 | 判断两个 IP 是否在同一网段 |
| 默认网关 | 访问外部网络时的下一跳 |
| 路由表 | 决定数据包下一步发往哪里 |
这一阶段主要对应:
| 网络层次 | 协议 / 概念 |
|---|---|
| 网络层 | IP、路由 |
为什么数据不能直接发给目标服务器呢?
我们先构建一个简单的网络:
当两台计算机需要通信的时候,你必须要连接他们,无论通过有线方式(通常是网线)或是无线方式(比如 WiFi 或蓝牙)。所有现代计算机都支持这些连接。

通常一个网络不仅限于两台计算机。你可以尽你所想地连接计算机,但是情况立刻变得复杂了。如果你尝试连接,比如说十台计算机,每台电脑有九个插头,总共需要 45 条网线。

为了解决这个问题,网络上的每台计算机需要连接到一个叫做网络交换机(network switch)的小型特殊计算机。交换机只干一件事:就像火车站的调度员,它要确保从一台计算机上发出的消息仅可以到达目标计算机。为了把消息发送给计算机 B,计算机 A 必须把信息发送给交换机,交换机将收到的信息转发给计算机 B。计算机 B 不会收到发给其他计算机的消息,发给计算机 B 的消息也不会传到局域网上的其他计算机上。
一旦我们把交换机加入到这个系统,我们的网络中便只需要十条网线:每台计算机一个插口,交换机上十个插口。

网络中的网
到目前为止一切都很好。但是我们要连接成百上千、上亿台计算机呢?当然一台交换机覆盖不了这么远,但是,如果你阅读得比较认真,我们曾提到交换机像其他计算机一样,所以我们为什么不把两个交换机彼此连接呢?

你可以想象我们可以无限地将交换机连接起来,形成这样的网络:

但是在现实中,这样会导致许多工程问题。数据包需要经过的交换机越多,到达目的地的时间就越长。而且你不能只依赖这种树状结构的交换机集群,因为一旦某个交换机节点故障,就会导致大面积的断网,这会使你的网络变得脆弱。为了解决这个问题,我们将每个网络保持在一个较小的规模,并使用一种名为路由器(router)的设备来连接每个网络。路由器是一种负责在不同网络之间转发消息的计算机,其运作原理类似邮局:当数据包到达时,它会读取收件人的地址,直接将数据包转发给正确的收件人,而无需经过层层中转。
我们来解释一下上面这段话,
首先路由器比纯使用交换机好在哪:
首先,交换机工作在数据链路层(二层),转发依据是 MAC 地址。当一个设备想找到另一个设备时,它会发送广播帧(比如 ARP 请求),交换机必须把这个广播复制到所有端口。
如果只有几十台设备,广播影响可以忽略。但如果把全世界的设备都连成一个二层网络,任何一台设备发出的广播,都会瞬间扩散到整个地球。每一台设备都会不断收到海量与自己无关的广播,CPU 被占用,带宽被耗尽,这就是广播风暴。结果就是,全世界网络一起瘫痪。
其次,交换机靠 MAC 地址表来寻址,二路由器使用IP地址来寻址,这样做的好处是可以把全世界切割成无数小的子网。你发往“大洋彼岸”的数据,只需要知道下一跳路由器在哪,完全不需要知道对方具体的 MAC 地址。
第三点,路由器直接可以通过路由协议(OSPF、BGP等),可以像导航地图一样实时计算最佳路径。当某条海缆断了,路由器能动态绕行,这是交换机二层网络永远做不到的。
为什么某个交换机节点故障了会导致大面积的断网,但路由器不会
使用纯交换机组成树形结构的网络像是这样的:
┌─────────────┐
│ 核心交换机 │ ⬅️ 这台坏了 👇
└──┬──┬──┬──┘
┌─────┘ │ └─────┐
┌────┴────┐ │ ┌────┴────┐
│ 交换机A │ │ │ 交换机B │
└──┬──┬──┘ │ └──┬──┬──┘
PC1 PC2 PC3 PC4 PC5
核心交换机一旦宕机,所有的 PC 全部无法通信,整个网络完全瘫痪。即便交换机A、B都完好,它们也失去了与上层连接的通路,没有任何备用路径(因为树形结构没有环路,或者即便有环路也会被 STP 阻塞成无环树)。
但如果使用路由器把网络切成小块的话是这样的:
网络1 (小) 网络2 (小) 网络3 (小)
┌─────────┐ ┌─────────┐ ┌─────────┐
│ PC1 PC2 │ │ PC3 PC4 │ │ PC5 PC6 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ 路由器1 │◄───────►│ 路由器2 │◄────────►│ 路由器3 │
└─────────┘ └────┬────┘ └─────────┘
⬆️ 这台路由器2 挂了
网络2 内部:PC3 和 PC4 之间仍然可以互相通信(它们连在同一个交换机或路由器内网口,属于同一广播域,不依赖路由器2)。
网络2 访问外部:网络2 里的设备无法再访问网络1、网络3 以及互联网。
网络1 和网络3:它们之间的通信完全不受影响,可以继续正常互访。
结论:路由器2 的故障只让它负责的“网络2”对外断网,影响范围被牢牢限制在一个小区域内,没有扩散到其他网络。
而且路由器还支持冗余协议(如 VRRP/HSRP)和动态路由,所以可以这样设计:
网络1 网络2 (关键网络)
┌──────┐ ┌──────┐
│ R1 │ │ 虚拟网关 │ (VIP: 192.168.2.1)
└──┬───┘ └──┬───┬──┘
│ │ │
│ ┌────────────┘ └────────────┐
│ │ │
┌──┴──────┴──┐ ┌────┴─────┐
│ 骨干网络 │ │ │
└──┬──────┬──┘ ┌──┴──┐ ┌──┴──┐
│ │ │ R2a │ │ R2b │ (真实路由器)
│ │ └──┬──┘ └──┬──┘
│ └──────────────┬────────┘ │
│ │ │
│ ┌──┴──────────────────┴──┐
│ │ 交换机 (网络2内部) │
│ └─────┬──────┬──────────┘
│ │ │
└─────(其他网络)───── PC3 PC4
R2a 和 R2b 是一对冗余路由器,共同对外虚拟出一个“虚拟网关”(VIP)。
正常情况下,R2a 负责转发,R2b 处于备份状态。
一旦 R2a 宕机,R2b 会立刻接管虚拟网关,网络2 的内部设备对外通信几乎不受影响(仅丢失极少量正在传输的包)。
对于网络1 和更远的网络,动态路由协议会立刻发现 R2a 失效,将流量自动绕行到 R2b,整个互联网不会因为这一台路由器故障而瘫痪。
这时候就有人要问了,为什么交换机不能使用冗余设计来消灭单点故障
这是因为交换机中MAC地址表大小是有限的,当交换机的地址表中没找到对应的MAC地址的时候,就会进行全网广播,然而当形成环路的时候,广播操作就会一直在交换机之间发生,然后无限死循环,造成全网瘫痪。所以,为了避免这种情况的发生,二层网络物理上不能有环路。
所以我们回到前面,我们就可以用路由器来将一个个小网络连接起来

下一步是将我们网络中的消息发送至目标网络。为此,我们将通过互联网服务提供商(ISP)连接至互联网。ISP 是管理特殊路由器的公司,这些路由器相互连接,并能访问其他 ISP 的路由器。因此,来自我们网络的消息将通过 ISP 网络的网络传输至目标网络。整个互联网正是由这样的网络基础设施构成的。

ARP:通过 IP 找到 MAC 地址
即使知道要把数据交给默认网关,主机还需要知道网关的 MAC 地址。
因为在局域网里,数据链路层真正转发的是 MAC 帧。
主机会发送 ARP 请求:
谁是 192.168.1.1?请告诉 192.168.1.100
路由器回复:
192.168.1.1 的 MAC 地址是 aa:bb:cc:dd:ee:ff
之后,本机会把数据封装成以太网帧,发给网关的 MAC 地址。
这里要注意一个重要点:
IP 地址用于跨网络寻址,MAC 地址用于同一个局域网内的下一跳转发。
这一阶段主要对应:
| 网络层次 | 协议 / 概念 |
|---|---|
| 数据链路层 | ARP、MAC、以太网帧 |
TCP 三次握手:建立可靠连接
在大多数情况下,一个HTTP请求会对应一个TCP连接。HTTP是基于TCP协议的,它使用TCP来传输HTTP请求和响应数据。
HTTP 1.0 和HTTP 2.0都基于TCP,而HTTP 3.0基于UDP
TCP 三次握手过程如下:
客户端 -> 服务器:SYN
服务器 -> 客户端:SYN + ACK
客户端 -> 服务器:ACK
三次握手的目的:
- 确认双方都能发送和接收数据
- 协商初始序列号
- 建立可靠传输连接
TCP 提供的能力包括:
| 能力 | 说明 |
|---|---|
| 可靠传输 | 丢包后可以重传 |
| 有序传输 | 接收方按顺序交付数据 |
| 流量控制 | 防止发送方把接收方打爆 |
| 拥塞控制 | 避免把网络链路打爆 |
| 端口复用 | 用端口区分不同应用进程 |
这一阶段主要对应:
| 网络层次 | 协议 |
|---|---|
| 传输层 | TCP |
TLS 握手:HTTPS 为什么安全
如果 URL 是 https://,TCP 连接建立后,还不能直接发送 HTTP 明文请求。
浏览器和服务器还要进行 TLS 握手。
TLS 握手主要做几件事:
- 协商 TLS 版本
- 协商加密套件
- 服务器发送证书
- 浏览器验证证书是否可信
- 双方协商出会话密钥
- 后续 HTTP 数据使用会话密钥加密传输
证书验证主要是为了确认:
我访问的真的是 www.example.com,而不是中间人伪造的网站。
TLS 解决的问题包括:
| 问题 | TLS 的作用 |
|---|---|
| 窃听 | 加密传输内容 |
| 篡改 | 校验数据完整性 |
| 冒充 | 通过证书验证服务器身份 |
TLS 通常被认为位于应用层和传输层之间,也可以理解为 HTTPS 的安全基础。
关于TCP和TLS我以前的TLS Poison 攻击学习中都有提到过
数据是如何被一层层封装的
浏览器生成 HTTP 请求后,数据不会直接裸奔到网络上。
它会被一层层封装:
HTTP 数据
↓ 加 TCP 头
TCP Segment
↓ 加 IP 头
IP Packet
↓ 加 Ethernet 头和尾
Ethernet Frame
↓ 转成电信号 / 光信号 / 无线电波
物理介质上传输
接收方则反过来一层层拆包:
Ethernet Frame
↓ 去掉以太网头尾
IP Packet
↓ 去掉 IP 头
TCP Segment
↓ 去掉 TCP 头
HTTP 数据
每一层只关心自己的职责:
| 层次 | 关注点 |
|---|---|
| 应用层 | 传什么业务数据 |
| 传输层 | 进程到进程,可靠性,端口 |
| 网络层 | 主机到主机,IP 和路由 |
| 数据链路层 | 相邻节点之间,MAC 和帧 |
| 物理层 | 比特如何在介质上传输 |
路由器在中间做了什么
数据包从你的电脑到服务器,通常会经过多个路由器。
每个路由器主要做这些事:
- 收到数据帧
- 拆掉当前链路层头部
- 查看 IP 包的目标地址
- 查询路由表
- 找到下一跳
- 重新封装新的链路层帧
- 转发出去
一个很重要的点:
源 IP 和目标 IP 通常在传输过程中不变,但每一跳的源 MAC 和目标 MAC 都会变化。
例如:
电脑 -> 家用路由器
源 MAC:电脑 MAC
目标 MAC:路由器 MAC
路由器 -> 下一跳运营商设备
源 MAC:路由器出口 MAC
目标 MAC:下一跳设备 MAC
IP 负责端到端,MAC 负责下一跳。
服务器处理请求
服务器收到 HTTP 请求后,可能经历:
Nginx / Apache / Caddy
↓
反向代理
↓
后端应用服务
↓
缓存 / 数据库
↓
生成响应
例如访问一个动态页面时,后端可能会:
- 解析请求路径和参数
- 校验 Cookie 或 Token
- 查询 Redis 缓存
- 查询 MySQL / PostgreSQL
- 渲染 HTML 或返回 JSON
- 交给 Web 服务器返回给浏览器
如果是静态资源,比如图片、CSS、JS,服务器可能直接从磁盘或 CDN 返回。
浏览器解析并渲染页面
浏览器收到 HTML 后,会开始渲染页面。
大致流程:
- 解析 HTML,构建 DOM 树
- 解析 CSS,构建 CSSOM 树
- 合并 DOM 和 CSSOM,生成渲染树
- Layout,计算元素位置和大小
- Paint,绘制像素
- Composite,合成图层并显示
如果 HTML 中引用了 CSS、JS、图片、字体等资源:
<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
<img src="/logo.png">
浏览器还会继续发起新的网络请求。
这些请求可能会:
- 复用已有 TCP/TLS 连接
- 使用缓存
- 重新 DNS 查询
- 走 CDN
- 使用 HTTP/2 多路复用
- 使用 HTTP/3 over QUIC
用这个过程串起网络分层
现在回头看,输入网址这件事正好把网络分层串起来了。
| 网络层次 | 在这个过程中的体现 |
|---|---|
| 应用层 | DNS、HTTP、HTTPS |
| 传输层 | TCP、UDP、端口、可靠传输 |
| 网络层 | IP、路由、跨网段转发 |
| 数据链路层 | MAC、ARP、以太网帧 |
| 物理层 | 网线、光纤、Wi-Fi 信号 |
如果用 OSI 七层模型表示:
| OSI 七层 | 对应例子 |
|---|---|
| 应用层 | HTTP、DNS |
| 表示层 | TLS、编码、压缩 |
| 会话层 | 会话状态、连接管理 |
| 传输层 | TCP、UDP |
| 网络层 | IP、路由 |
| 数据链路层 | Ethernet、MAC、ARP |
| 物理层 | 电信号、光信号、无线电波 |
总流程图
输入 URL
↓
浏览器解析 URL
↓
DNS 查询域名对应 IP
↓
判断目标是否在同一网段
↓
ARP 获取下一跳 MAC 地址
↓
TCP 三次握手
↓
TLS 握手
↓
发送 HTTP 请求
↓
服务器处理请求
↓
返回 HTTP 响应
↓
数据逐层拆包
↓
浏览器解析并渲染页面
总结
输入网址并按下回车,看起来只是一个简单动作,但背后串起了计算机网络的大部分核心知识。
DNS 负责把域名变成 IP,IP 和路由负责把数据送到目标网络,ARP 和 MAC 负责局域网内的下一跳转发,TCP 负责可靠连接,TLS 负责安全加密,HTTP 负责应用层语义,浏览器最终负责解析和渲染页面。
如果把这些知识孤立地背,很容易混乱;但如果沿着“一次网页访问”的路径去看,每一层为什么存在、解决什么问题,就会清楚很多。