第5章:应用层(Application Layer)
一、导读
1.1 本章学习目标
第5章讲解应用层协议——直接为终端用户应用提供服务的协议。从 DNS 到 HTTP,从 SMTP 到 P2P,本章覆盖了互联网上最常用的应用层协议。
本章核心学习目标:
- 掌握 DNS 的工作原理:层次化命名、递归/迭代查询、缓存
- 理解 HTTP 的演进:HTTP/1.0 → HTTP/1.1 → HTTP/2 → HTTP/3
- 掌握 SMTP/POP3/IMAP:电子邮件系统的协议栈
- 理解 P2P 文件共享:BitTorrent 的 choked/interested 机制
- 了解 CDN 的工作原理:内容分发如何提高性能
1.2 为什么本章如此重要
应用层是程序员最常接触的网络层。理解 HTTP、DNS 的工作原理,对于 Web 开发、性能优化和问题排查至关重要。
1.3 核心问题引导
DNS 为什么同时使用 UDP 和 TCP?
HTTP/2 的多路复用如何解决 HTTP/1.1 的队头阻塞问题?
CDN 如何决定将内容缓存在哪个边缘节点?
二、核心概念详解
2.1 DNS
DNS 层次结构:
. (根)
├── com.
│ ├── google.com.
│ └── example.com.
├── org.
└── cn.
└── example.cn.
查询类型:
- 递归查询: 客户端 → 本地 DNS → 根 → TLD → 权威 DNS
客户端只发一次请求,本地 DNS 负责完成全部查询
- 迭代查询: 本地 DNS 依次查询各级 DNS
每级 DNS 返回下一级的地址
DNS 记录类型:
- A: IPv4 地址
- AAAA: IPv6 地址
- CNAME: 别名
- MX: 邮件服务器
- NS: 权威名称服务器
- TXT: 文本记录(SPF、DKIM 等)
DNS 缓存:
- 浏览器缓存: ~30 秒
- OS 缓存: ~120 秒
- 递归 DNS 缓存: 根据 TTL
- TTL 过期后重新查询2.2 HTTP 演进
HTTP/1.0 (1996):
- 每个请求建立新连接
- 无状态,无持久连接
- 问题: 连接建立开销大(TCP 握手 + 慢启动)
HTTP/1.1 (1997):
- 持久连接 (Keep-Alive): 一个连接服务多个请求
- 管线化 (Pipelining): 连续发送请求,不等响应
→ 队头阻塞: 响应必须按请求顺序返回
- 分块传输编码 (Chunked Transfer)
- Host 头: 支持虚拟主机
HTTP/2 (2015):
- 多路复用: 一个连接上并行多个流
→ 解决队头阻塞
- 头部压缩 (HPACK)
- 服务器推送
- 二进制分帧
- 流优先级
HTTP/3 (2022):
- 基于 QUIC (UDP)
- 解决 TCP 层的队头阻塞
- 0-RTT 连接建立
- 连接迁移 (Connection ID)2.3 电子邮件系统
邮件发送流程:
发送方 → MUA (邮件客户端)
→ SMTP → MSA (邮件提交代理)
→ SMTP → MTA (邮件传输代理/relay)
→ SMTP → MDA (邮件投递代理)
→ 收件方 MUA (通过 POP3/IMAP 收取)
SMTP:
- 端口 25 (MTA-MTA), 587 (MUA-MSA)
- 基于文本的协议
- 命令: HELO, MAIL FROM, RCPT TO, DATA, QUIT
POP3 vs IMAP:
- POP3: 下载到本地,删除服务器副本
端口 110 (明文), 995 (SSL)
- IMAP: 在服务器上管理邮件
支持文件夹、搜索、部分下载
端口 143 (明文), 993 (SSL)三、实战案例
3.1 案例一:HTTP/2 多路复用演示
python
import httpx
import time
# HTTP/1.1 vs HTTP/2 性能对比
url = "https://http2.golang.org/reqinfo"
# HTTP/1.1
start = time.time()
with httpx.Client(http1=True) as client:
for i in range(10):
resp = client.get(url)
http1_time = time.time() - start
# HTTP/2
start = time.time()
with httpx.Client(http2=True) as client:
for i in range(10):
resp = client.get(url)
http2_time = time.time() - start
print(f"HTTP/1.1: {http1_time:.3f}s")
print(f"HTTP/2: {http2_time:.3f}s")
print(f"加速比: {http1_time/http2_time:.1f}x")四、本章小结
DNS 是互联网的"电话簿",层次化命名支持全球规模的域名解析
HTTP 从 1.0 到 3 持续演进,核心目标是减少延迟、提高并发
电子邮件 使用 SMTP 发送、POP3/IMAP 收取,是互联网最早的应用之一
五、思考与练习
思考题
DNS 为什么主要使用 UDP 而非 TCP?什么情况下 DNS 会使用 TCP?
HTTP/3 基于 QUIC (UDP) 而非 TCP,为什么?
编程练习
实现一个简单的 DNS 解析器,支持递归查询。
实现一个支持 HTTP/1.1 持久连接的简单 Web 服务器。