5Computer Networks: A Systems Approach(第6版)

应用层

网络应用

DNSHTTPSMTPP2P网络

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第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 服务器。


5/7应用层
0%