场景设定

小李带着笔记本走进图书馆,插上网线,打开浏览器,
在地址栏输入  https://www.example.edu  并回车。

⭐ 两秒后页面出现。

这两秒里,发生了什么?

网络环境

笔记本 MAC:   AA:AA:AA:AA:AA:AA     (尚无 IP 地址)
校园交换机:   一台以太网交换机
校园路由器:   内网侧 IP 192.168.1.1,MAC RR:RR:RR:RR:RR:RR
DHCP 服务器:  与路由器同一台设备
本地 DNS:     192.168.1.53
目标服务器:   www.example.edu,通过 CDN 提供服务

第一幕:接入网络(第 18、24 讲)

步骤 1:DHCP —— 获得身份 ⭐

⚠️ 此刻笔记本什么都没有:没有 IP 地址,不知道网关在哪,不知道 DNS 在哪。它连"问一句"都做不到,因为发任何单播包都需要目的地址。

唯一的出路是广播。

① DHCP DISCOVER
   应用层: DHCP 报文
   传输层: UDP,源端口 68 → 目的端口 67
   网络层: ⭐ 源 IP = 0.0.0.0(我还没有地址)
           ⭐ 目的 IP = 255.255.255.255(广播)
   链路层: ⭐ 目的 MAC = FF:FF:FF:FF:FF:FF(广播)
           源 MAC = AA:AA:AA:AA:AA:AA

② 交换机收到广播帧 → ⭐ 从所有其他端口泛洪(第 24 讲)
   ⭐ 同时学习:(AA:AA:..., 端口 5)

③ DHCP 服务器回 OFFER:「给你 192.168.1.100」
④ 笔记本回 REQUEST(仍是广播,让其他 DHCP 服务器知道自己没被选中)
⑤ 服务器回 ACK,租期 12 小时

笔记本此刻获得了四样东西(第 18 讲):

⭐ 自己的 IP:      192.168.1.100
⭐ 子网掩码:       255.255.255.0  (/24)
⭐ 默认网关:       192.168.1.1
⭐ 本地 DNS 服务器: 192.168.1.53

📌 注意后两项和 IP 地址同等重要。只有 IP 而不知道网关,只能在本子网内通信;不知道 DNS,就只能用 IP 地址访问网站。

⚠️ 故障诊断:如果这一步失败,主机会自动配置一个 169.254.x.x链路本地地址(第 18 讲)。看到这个地址,就意味着 DHCP 没成功——这是排障时的第一个信号。


第二幕:找到 DNS 服务器(第 24 讲)

步骤 2:ARP —— 从 IP 到 MAC ⭐

笔记本要向 DNS 服务器 192.168.1.53 发查询。但链路层需要 MAC 地址,而它只有 IP 地址

① 笔记本比较 192.168.1.53 与自己的子网 192.168.1.0/24
   ⭐ 在同一子网 → 可以直接通信,不需要经过路由器

② 查本地 ARP 表 → 没有该条目

③ ⭐ 广播 ARP 请求:「谁是 192.168.1.53?请告诉 192.168.1.100」
   目的 MAC = FF:FF:FF:FF:FF:FF

④ DNS 服务器【单播】回复自己的 MAC

⑤ 笔记本缓存到 ARP 表(TTL 约 20 分钟)

📌 这一步展示了两套地址体系的分工(第 24 讲):IP 用于确定"要找谁",MAC 用于确定"这一跳交给谁"。


第三幕:域名解析(第 7 讲)

步骤 3:DNS 查询 ⭐

① 笔记本 → 本地 DNS (192.168.1.53):⭐ 递归查询
   「www.example.edu 的 A 记录是什么?」
   (UDP 53,因为一问一答不值得建 TCP 连接 —— 第 10 讲)

② 本地 DNS 缓存未命中 → 开始【迭代查询】:

   本地 DNS → 根服务器
       ⭐ 实际到达的是 anycast 路由到的最近实例(第 19 讲)
       ← 「去问 .edu 的 TLD 服务器」

   本地 DNS → .edu TLD 服务器
       ← 「去问 ns1.example.edu」

   本地 DNS → example.edu 权威服务器
       ← ⭐ 返回一条 CNAME:www.example.edu → edge.cdn-provider.net
          (说明这个站点托管在 CDN 上 —— 第 6 讲)

   本地 DNS → CDN 的权威 DNS
       ⭐ CDN 根据【本地 DNS 的位置】判断用户大致在哪
       ← 返回一个"近"的边缘节点 IP:203.0.113.50
          TTL 只有 60 秒(CDN 需要频繁调度)

③ 本地 DNS 缓存结果,返回给笔记本

这一步的耗时通常是 20–150 ms,如果全部命中缓存则只要 1–2 ms(第 7 讲例题)。

⚠️ 故障诊断:「网页打不开但 ping IP 通」= DNS 出了问题。用 dig 直接查询可以定位是本地 DNS 还是权威服务器的问题。


第四幕:把分组送出校园(第 17、18、20、21、24 讲)

步骤 4:判断目的地在哪,找到网关 ⭐

① 笔记本比较目的 IP 203.0.113.50 与自己的子网 192.168.1.0/24
   ⭐ 不在同一子网 → 必须交给【默认网关】

② ARP 查询网关 192.168.1.1 的 MAC(不是服务器的!)
   ⭐ 笔记本永远无法用 ARP 查到 203.0.113.50 的 MAC ——
     ARP 请求是广播,不跨越路由器(第 24 讲)

③ 构造帧:
   ┌────────────────────────────────────────────────┐
   │ 目的 MAC: RR:RR:...(路由器) │ 源 MAC: AA:AA:... │  ← ⭐ 逐跳
   │ 目的 IP: 203.0.113.50       │ 源 IP: 192.168.1.100│ ← ⭐ 端到端
   └────────────────────────────────────────────────┘

步骤 5:NAT 改写(第 18 讲)

校园路由器(若做 NAT):
   ⭐ 改写源 IP: 192.168.1.100 → 公网 IP 198.51.100.7
   ⭐ 改写源端口: 51000 → 5001
   ⭐ 记入 NAT 转换表
   ⭐ 重算 IP 头校验和【和】TCP 校验和(因为伪首部 —— 第 10 讲)

步骤 6:逐跳转发(第 17、20、21 讲)

每一跳路由器:
① 剥掉入链路的帧头,验证 CRC(第 23 讲)
② ⭐ 对目的 IP 做【最长前缀匹配】查转发表(第 17 讲,TCAM 硬件,纳秒级)
③ TTL 减 1,重算 IP 头校验和(第 18 讲)
④ ⭐ 构造【新的】链路层帧头(新的源/目的 MAC)
⑤ 从对应输出端口发出,可能在输出队列中排队(第 3、17 讲)

转发表是怎么来的?

校园网内部:  ⭐ OSPF 用链路状态算法(Dijkstra)算出(第 20、21 讲)
跨越 AS:     ⭐ BGP 通告的 AS_PATH,按 LOCAL_PREF → AS_PATH 长度 → 热土豆
             选出(第 21 讲)
             ⭐ 注意:这条路径是【商业策略】决定的,不一定是物理最短

📌 **走到这里,第 17–24 讲的内容全部用上了。**一个分组从笔记本走到 CDN 边缘节点,可能经过 8–15 跳,跨越 2–4 个 AS。


第五幕:建立连接(第 13、14 讲)

步骤 7:TCP 三次握手

笔记本                                     CDN 边缘服务器
   │─ SYN,     Seq=x ─────────────────────────▶│
   │◀ SYN+ACK, Seq=y, Ack=x+1 ─────────────────│
   │─ ACK,     Seq=x+1, Ack=y+1 ──────────────▶│

⭐ 耗时:1 个 RTT
⭐ 同时协商:MSS、窗口缩放因子、SACK 支持(第 13、14 讲)

步骤 8:TLS 握手(第 27、28 讲)

   │─ ClientHello(支持的套件、⭐ 随机数、⭐ DH 公开值)─▶│
   │◀ ServerHello + ⭐ 证书 + DH 公开值 + Finished ────│
   │─ Finished ──────────────────────────────────────▶│

⭐ TLS 1.3:1 个 RTT

客户端在这里做的事(第 28 讲的六步验证):

① 验证证书签名
② 追溯信任链到预置的根 CA
③ 检查有效期
④ ⭐ 检查 SAN 中包含 www.example.edu
⑤ 检查吊销状态(OCSP Stapling)
⑥ 检查用途扩展

密钥交换用 ECDHE → 具备前向保密(第 28 讲)。

⚠️ 故障诊断:「你的连接不是私密连接」的警告,绝大多数来自 ③(证书过期)或 ④(域名不匹配)。


第六幕:获取内容(第 5、6、16 讲)

步骤 9:HTTP 请求

GET / HTTP/2
:authority: www.example.edu
:scheme: https
user-agent: Mozilla/5.0
accept-encoding: gzip, br
cookie: session=abc123          ⭐ 第 5 讲

步骤 10:服务器响应与 TCP 慢启动 ⭐

服务器返回 HTML。此时 TCP 处于【慢启动】阶段(第 16 讲):

RTT 1:  cwnd = 10 MSS(现代初始窗口)→ 发出约 14 KB
RTT 2:  cwnd = 20 → 约 29 KB
RTT 3:  cwnd = 40 → 约 58 KB
        ⭐ 指数增长,直到 ssthresh 或出现丢包

这解释了一个重要现象

对于小于约 15 KB 的页面,传输时间几乎完全由 RTT 决定,与带宽无关。 这就是为什么降低 RTT(用 CDN)比增加带宽更能改善网页加载速度(第 3、6 讲)。

步骤 11:解析 HTML,获取其余对象

浏览器解析 HTML,发现还需要 CSS、JS、图片、字体……

⭐ HTTP/2 在【同一条】TCP 连接上多路复用所有请求(第 6 讲)
   → 没有应用层队头阻塞
   → 但若这条 TCP 连接上出现丢包,⭐ 所有流一起卡住(传输层队头阻塞)
   → 若用 HTTP/3(QUIC),则只有丢包的那个流受影响

部分对象可能来自不同的域名回到步骤 3,再做一次 DNS 解析

步骤 12:渲染

浏览器逐步渲染页面。
⭐ 用户看到"页面出来了",通常发生在 HTML + 关键 CSS 到达之后,
   而不是所有资源都下载完之后。

完整时间线

假设 RTT = 40 ms,所有缓存为空:

阶段 耗时 累计
DHCP(4 个报文,本地) ~5 ms 5 ms
ARP(DNS 服务器) ~1 ms 6 ms
DNS 递归解析(根+TLD+权威+CDN) ~120 ms 126 ms
ARP(网关) ~1 ms 127 ms
TCP 三次握手(1 RTT) 40 ms 167 ms
TLS 1.3 握手(1 RTT) 40 ms 207 ms
HTTP 请求 + 首字节(1 RTT) 40 ms 247 ms
HTML 传输(慢启动 2 轮) 80 ms 327 ms
关键 CSS/JS(复用连接,1–2 RTT) 80 ms 407 ms
首屏渲染 ~0.4 秒

注意这个表格里最大的一项是 DNS(120 ms),而它在缓存命中时只要 1 ms。

📌 优化网页速度的优先级,可以直接从这张表读出来

① ⭐ 减少 RTT       → CDN、边缘节点(省下 3 个 RTT × 距离)
② ⭐ 减少 RTT 的个数 → HTTP/3 的 0-RTT、连接复用、预连接
③ ⭐ DNS 预解析      → dns-prefetch、preconnect
④ 减少关键路径资源   → 内联关键 CSS、延迟加载非关键资源
⑤ 增加带宽          → ⭐ 对小页面几乎无效(被慢启动和 RTT 支配)

故障诊断速查表 ⭐

这张表是网络工程师的日常工具,也是面试高频题。

症状 最可能的环节 排查手段
得到 169.254.x.x 地址 DHCP 失败 检查线路、DHCP 服务器、VLAN
ping 网关不通 ARP 或二层链路 arp -a、检查交换机端口
ping IP 通,域名不通 DNS dig、换 DNS 服务器测试
DNS 解析出的 IP 不对 缓存 / 投毒 / CDN 调度 dig +trace、清缓存
TCP 连不上(超时) 路由、防火墙丢包 traceroutetelnet host port
TCP 连不上(立即拒绝) 目标端口无进程监听(收到 RST) 检查服务是否启动
证书警告 证书过期 / 域名不匹配 浏览器查看证书详情
连接建立成功但传大数据卡死 PMTUD 黑洞(ICMP 被屏蔽) 减小 MSS 测试(第 22 讲)
速度慢且 ping 值高 Bufferbloat 空载与满载时分别测 ping(第 16 讲)
速度慢但 ping 正常 窗口受限 / 丢包 / 服务器慢 检查窗口缩放、丢包率
请求-响应有稳定的 40/200 ms 延迟 Nagle + 延迟确认 TCP_NODELAY(第 14 讲)
只有部分用户访问不了 BGP 路由或 CDN 节点问题 从不同地区测试、查 BGP 通告

贯穿全课的九条主线 ⭐

如果这门课只能记住九件事,就是这些。

1️⃣ 智能在边缘,网络保持简单(端到端原则)

出现在:IP 的 best-effort 服务模型、拥塞控制放在端系统、DASH 的客户端自适应、TCP 而非路由器负责可靠性。

它的例外同样重要:802.11 的链路层重传——端到端原则允许在有明确性能收益时做局部重复

2️⃣ 分层与沙漏:可扩展性的来源,也是演进的枷锁

IP 作为唯一的窄腰让互联网无限可扩展;同时也让 IPv6 用三十年还没换完。层次越低,改变越难。

3️⃣ 层次化 + 汇总 = 可扩展性

出现在:DNS 的三级层次、CIDR 地址聚合、OSPF 的区域、BGP 的 AS 分层。在层次边界上把细节压缩成摘要。

4️⃣ 同一个问题在不同层反复出现

  • 队头阻塞:HTTP/1.1、TCP 字节流、交换机输入队列
  • 边界标记与转义:SMTP 点填充、链路层字节填充
  • 指数退避:TCP 超时、以太网碰撞
  • 可靠传输:TCP、802.11 链路层、应用层重试

认出这种同构,比记住每一个具体协议更有价值。

5️⃣ 统计复用:互联网的经济基础

分组交换赌"大家不会同时用"(第 2 讲)。这个赌注在绝大多数时候是赢的,也正因如此互联网才便宜到人人可用。网络切片是对这个赌注的局部撤回(第 26 讲)。

6️⃣ 反馈控制:在无知中收敛

TCP 不知道链路有多宽,只能"涨到出问题,退回来,再涨"。⭐ AIMD 被数学证明能让完全分布式的、自私的参与者收敛到公平——这是全课最优雅的结论(第 15 讲)。

7️⃣ 可部署性压倒理论优势

  • TCP/IP 打败 OSI
  • 以太网打败令牌环
  • NAT 苟活了 IPv4
  • 间接路由打败直接路由
  • QUIC 建在 UDP 上而不是定义新的传输层协议
  • TLS 赢过 IPsec

共同点:赢的那个不要求别人改变。

8️⃣ 互联网诞生于一个相互信任的环境

IP 不认证源地址、DNS 不认证响应、BGP 不认证前缀所有权、ARP 不认证回复、SMTP 不认证发件人。⭐ 几乎所有的网络安全问题,都源于这个假设在 1990 年代后不再成立,而底层协议已经无法轻易更换。

9️⃣ 最重要的改进卡在激励而非技术

BCP 38(防 IP 欺骗)、IPv6、BGPsec、DNSSEC——技术早已就绪,部署卡住的原因完全相同:⭐ 投入成本的人不是主要受益的人。

🎯 这是这门课教给你的、最超出技术本身的一课大规模系统的演化,由激励结构决定,而不只由技术优劣决定。


五层协议栈总览(期末速查)

解决什么问题 关键协议 关键机制 讲次
应用 进程间交换有意义的消息 HTTP/1.1,2,3 · DNS · SMTP · DASH 请求-响应、缓存、CDN、无状态+Cookie 5–9
传输 把主机到主机变成进程到进程,并造出可靠管道 TCP · UDP · QUIC 端口复用、序号/确认、滑动窗口、AIMD 10–16
网络 跨越异构网络把分组送到目的主机 IP · ICMP · OSPF · BGP 最长前缀匹配、CIDR、Dijkstra、路径向量 17–22
链路 在相邻节点间可靠地传一个帧 Ethernet · 802.11 · ARP 成帧、CRC、CSMA/CD、CSMA/CA、自学习 23–25
物理 在介质上传比特 调制、编码 25
横切 机密性、完整性、认证 TLS · IPsec · WPA3 混合加密、Nonce、证书、AEAD 27–28

学完之后往哪走

方向 建议起点
系统与内核 读 Linux 网络栈源码;TCP/IP Illustrated Vol. 2
协议实现 完整做一遍 Stanford CS144(自己实现一个 TCP)
数据中心网络 Clos 拓扑、RDMA/RoCE、DCTCP、可编程交换机(P4)
网络安全 《Serious Cryptography》;做 CTF 的 pwn/network 方向
性能与测量 RFC 6349、iperf3、eBPF 网络可观测性
无线与 5G 3GPP 规范;软件定义无线电(GNU Radio)
前沿研究 SIGCOMM、NSDI 的会议论文

例题(Worked Example)

题目:小李在图书馆访问 https://shop.example.com 时遇到以下现象。对每一个现象,指出最可能的问题环节判断依据下一步排查动作

(a) 浏览器显示"找不到服务器 IP 地址"。 (b) 页面能打开,但每次点击都要等 3 秒才有反应,而 ping 服务器只有 30 ms。 (c) 页面能打开,但浏览器提示"你的连接不是私密连接"。 (d) 首页秒开,但点击某个大图片就一直转圈,最终超时。 (e) 小李的电脑正常,但同宿舍的同学都打不开这个网站,其他网站都正常。 (f) 一边下载大文件时,网页浏览变得极慢,ping 值从 20 ms 涨到 900 ms。

解答

(a) DNS 解析失败(第 7 讲)

判断依据:浏览器明确报"找不到 IP 地址",说明连 TCP 连接都没尝试建立。
下一步:
   ① dig shop.example.com  —— 看本地 DNS 是否能解析
   ② dig @8.8.8.8 shop.example.com  —— 换权威路径测试
   ③ 若换 DNS 就能解析 → 本地 DNS 服务器故障或被污染
   ④ dig +trace  —— 定位是根、TLD 还是权威服务器出问题

(b) Nagle 算法 + 延迟确认的交互,或服务器端处理慢(第 14 讲)

判断依据:⭐ ping 只有 30 ms 说明网络路径正常,问题不在传输。
        若延迟是【稳定的 40 ms 或 200 ms 的倍数】→ 强烈指向 Nagle + 延迟确认。
        若延迟是 3 秒这种量级且不规律 → 更可能是【服务器端处理慢】或数据库查询慢。
下一步:
   ① 抓包看时间戳分布:延迟是发生在"请求发出到首字节"(服务器慢)
     还是"数据分两次发出之间"(Nagle)
   ② 若是 Nagle → 在服务端/客户端设置 TCP_NODELAY
   ③ 若是服务器慢 → 这不是网络问题,转给后端团队

(c) 证书验证失败(第 28 讲)

判断依据:TLS 握手已经开始(说明 DNS、TCP 都正常),卡在证书验证。
下一步(按可能性排序):
   ① ⭐ 检查本机【系统时间】—— 时间错误会导致有效期检查失败,
     这是最常见也最容易被忽略的原因
   ② 点开证书详情,看是哪一步失败:
      • 过期 → 网站方问题
      • ⭐ 域名不匹配(SAN 中没有 shop.example.com)→ 配置错误
      • 颁发者不受信任 → ⚠️ 可能存在【TLS 中间人拦截】
   ③ 若证书颁发者是陌生的机构名 → ⭐ 高度怀疑网络被劫持,立即停止输入密码

(d) PMTUD 黑洞(第 18、22 讲)

判断依据:⭐ 这是一个非常有特征的症状组合 ——
        【小请求正常(首页秒开)】+【大数据传输卡死】
        说明 TCP 握手成功、小分组能通,但【大分组被静默丢弃】。
        
原因:路径上某段 MTU 较小,需要发 ICMP"需要分片"(类型 3 代码 4),
     但该 ICMP 被某处防火墙屏蔽 → ⭐ 发送方永远不知道要减小分组
     
下一步:
   ① ping -M do -s 1472 服务器IP   (测试不分片的最大包)
     逐步减小,找到实际可通过的 MTU
   ② 临时验证:把本机 MTU 调小(如 1400)看是否恢复
   ③ 长期解决:在路径上放行 ICMP 类型 3 代码 4,或在服务端启用 MSS clamping

(e) BGP 路由问题或 CDN 节点故障(第 6、21 讲)

判断依据:⭐ 关键在于"同宿舍其他人也不行,但其他网站正常"——
        问题既不在单台机器,也不在整条接入链路,
        而在【到这个特定目的地的路径】上。
        
可能原因:
   • 该 CDN 边缘节点故障,而 DNS 仍在把本地区用户导向它
   • 中间某个 AS 的 BGP 路由异常或前缀被撤销
   • 该网站封禁了本校的出口 IP 段
   
下一步:
   ① traceroute 看在哪一跳断掉
   ② 用外部工具(不同地区的探测点)测试,判断是全局故障还是局部
   ③ dig 看解析到哪个 CDN 节点,尝试手工指定其他节点 IP 测试
   ④ 若 traceroute 在某个 AS 内部断掉 → 联系 ISP

(f) 缓冲区膨胀(Bufferbloat)(第 16、17 讲)

判断依据:⭐ 这是 bufferbloat 的教科书级症状 ——
        【有大流量时 ping 值暴涨 10 倍以上】,且没有丢包。
        
原因:下载的 TCP 流(基于丢包的拥塞控制,如 CUBIC)会持续增大窗口,
     直到把上行/下行路径上的大缓冲区【填满】才收到丢包信号。
     ⭐ 排队的数据不增加任何吞吐量,只增加所有流的时延。
     
下一步:
   ① 用 flent / waveform bufferbloat test 量化空载与满载时的时延差
   ② ⭐ 在家用路由器上启用【FQ-CoDel 或 CAKE】队列管理
   ③ 把上行带宽限制到实测值的 90–95%(把队列从运营商设备移到自己可控的设备上)
   ④ 若可行,让大流量应用使用 ⭐ BBR(不填缓冲区)

随堂自测(期末综合题)

  1. 完整叙述从插上网线到看到网页的全部步骤,指出每一步用到的协议和层次。
  2. 为什么笔记本必须用广播发 DHCP DISCOVER?为什么用 UDP 而不是 TCP?
  3. 访问一个外网 IP 时,主机 ARP 查询的是谁的 MAC?为什么不能查目标服务器的?
  4. 一个网页请求中,通常要经过几个 RTT 才能看到首字节?分别是哪些?
  5. 为什么说「对小页面,增加带宽几乎无效」?
  6. 分组在每一跳被改写了什么、没被改写什么?
  7. ⭐ 列出全课的九条主线,并各举一个例子。
  8. 一个用户报告「网站时快时慢」,给出至少五种可能原因和对应的排查方法。

本讲要点回顾

  • 一次网页访问依次用到:⭐ DHCP → ARP → DNS → ARP → TCP 握手 → TLS 握手 → HTTP → 慢启动
  • DNS 通常是整条链路上耗时最长的一环(缓存未命中时)。
  • 对小页面,加载时间由 RTT 的个数决定,与带宽几乎无关CDN 比宽带更有效
  • IP 地址端到端不变,MAC 地址逐跳更换,NAT 是显著的例外。
  • 故障诊断的关键是按层定位:先确认二层通不通,再三层,再 DNS,再传输,最后应用。
  • 九条主线:端到端原则 · 沙漏与僵化 · 层次化汇总 · 跨层同构 · 统计复用 · 反馈控制 · 可部署性优先 · 信任假设的崩塌 · 激励决定演化。

课程结语

网络这门课有一件事和别的课不同:你学到的每一个机制,此刻都在你面前的这台设备上运行着。

你现在读到这行字,它经过了 TCP 的滑动窗口、CUBIC 的拥塞窗口、某台路由器的最长前缀匹配、某个 AS 的 BGP 策略、一次 TLS 1.3 握手、以及至少一次以太网 CRC 校验。这些都不再是名词了。

更重要的是,你现在应该能看出这个系统不是被设计出来的,而是长出来的。它有 1974 年的假设,1983 年的 512 字节限制,1993 年的地址危机补丁,2015 年的加密普及,和至今没解决的信任问题。它在很多地方并不优雅,但它在四十年里从几百台主机长到几百亿台设备,从未整体停机过一次。

⭐ **这是人类造过的最大的、还在运行的工程系统。**而现在你知道它是怎么工作的了。