#计算机网络学习笔记2
应用层原理
网络应用程序体系结构
客户-服务器体系结构(client-server architecture)
- 服务器:总是打开的主机,有固定的 IP 地址,数据中心用于扩展
- 客户:间歇性连接,可以是动态 IP,客户之间不直接通信
P2P 体系结构(peer-to-peer architecture)
- 对总是打开的服务器依赖最小
- 任意端系统(对等方,peer)之间直接通信
- 对等方间歇性连接且可以改变 IP 地址
- 自扩展性(self-scalability):每个对等方既产生负载也提供服务能力
进程通信
进程(process):在主机上运行的程序
- 在同一主机内:两个进程使用进程间通信(由 OS 管理)
- 不同主机之间:通过交换报文(message)进行通信
在一对进程的通信会话中:
- 客户进程:发起通信的进程
- 服务器进程:等待联系的进程
P2P 中一个进程既可以是客户也可以是服务器
套接字
进程通过套接字(socket)向网络发送/接收报文
套接字是应用层与传输层之间的接口,也称为应用程序和网络之间的应用程序编程接口(Application Programming Interface, API)
TCP socket:源 IP,源端口,目标 IP,目标端口
UDP socket:本 IP,本端口
进程寻址
进程的标识需要两个信息:
- 主机的 IP 地址(32 位)
- 目的主机上接收进程的端口号(port number)
常见端口号:HTTP 80,HTTPS 443,SMTP 25,DNS 53
应用层协议
应用层协议定义了:
- 交换的报文类型(请求/响应)
- 各种报文类型的语法(字段及其描述)
- 字段的语义
- 进程何时以及如何发送和响应报文的规则
公开协议:由 RFC 定义(如 HTTP, SMTP)
专有协议:如 Skype
运输服务的需求
| 需求 | 说明 |
|---|---|
| 可靠数据传输 | 某些应用要求 100% 可靠(如文件传输),某些应用可以容忍丢失(如音视频) |
| 吞吐量 | 带宽敏感型应用需要保证最小吞吐量(如视频),弹性应用则不需要(如邮件) |
| 定时 | 某些应用要求低延迟(如交互式游戏) |
| 安全性 | 加密、数据完整性、端点鉴别 |
常见应用对传输服务的需求:
| 应用 | 数据丢失 | 吞吐量 | 时间敏感性 |
|---|---|---|---|
| 文件传输/下载 | 不能丢失 | 弹性 | 不敏感 |
| 电子邮件 | 不能丢失 | 弹性 | 不敏感 |
| Web 文档 | 不能丢失 | 弹性 | 不敏感 |
| 实时音视频 | 容忍丢失 | 音频 5kbps~1Mbps,视频 10kbps~5Mbps | 敏感(100ms 级) |
| 存储的音视频 | 容忍丢失 | 同上 | 敏感(数秒级) |
| 交互式游戏 | 容忍丢失 | kbps~Mbps | 敏感(100ms 级) |
| 即时消息 | 不能丢失 | 弹性 | 敏感/不敏感 |
TCP 与 UDP 服务
TCP 服务:
- 面向连接:客户和服务器进程之间建立连接
- 可靠传输:保证数据完整无差错按序到达
- 流量控制:发送方不会淹没接收方
- 拥塞控制:当网络出现拥塞时抑制发送方
- 不提供:定时、最小吞吐量保证、安全性
UDP 服务:
- 无连接
- 不可靠数据传输
- 不提供:可靠性、流量控制、拥塞控制、定时、吞吐量保证、安全性
TLS(Transport Layer Security):在 TCP 之上提供加密的 TCP 连接,包括数据完整性和端点鉴别
常见应用使用的传输层协议:
| 应用 | 应用层协议 | 传输层协议 |
|---|---|---|
| Web | HTTP/1.1, HTTP/2 | TCP |
| Web | HTTP/3 | UDP(QUIC) |
| 电子邮件 | SMTP | TCP |
| 远程终端 | Telnet / SSH | TCP |
| 文件传输 | FTP | TCP |
| 流媒体 | DASH (HTTP) | TCP 或 UDP |
| 域名解析 | DNS | UDP(通常),TCP(大响应/区域传送) |
| 网络管理 | SNMP | UDP |
| 网络电话 | SIP/RTP | UDP(通常) |
HTTP
超文本传输协议(HyperText Transfer Protocol)
- Web 的应用层协议
- 客户-服务器模型
- 使用 TCP:客户发起到服务器 80 端口的 TCP 连接,服务器接受连接,交换 HTTP 报文,关闭连接
- HTTP 是无状态的(stateless):服务器不保存关于客户的任何信息
非持续连接与持续连接
非持续连接 HTTP(HTTP/1.0):
- 每个 TCP 连接最多传送一个对象
- 下载多个对象需要多个 TCP 连接
非持续连接的响应时间:

\[\text{响应时间} = 2 \times RTT + \text{文件传输时间}\]
其中第一个 RTT 用于建立 TCP 连接(三次握手的前两次),第二个 RTT 用于 HTTP 请求和响应的前几个字节
持续连接 HTTP(HTTP/1.1):
- 服务器在发送响应后保持 TCP 连接打开
- 同一客户-服务器之间的后续 HTTP 报文通过同一连接发送
- 客户一旦遇到一个引用对象就可以发送请求
- 所有引用对象可以在一个 TCP 连接上依次请求
e.g.: 一个 Web 页面包含 1 个 HTML 基本文件和 10 个引用图片,RTT = 100ms,文件传输时间忽略
非持续连接(HTTP/1.0): - 获取 HTML:1 次 TCP 握手 + 1 次请求/响应 = 2 RTT = 200ms - 获取 10 个图片:每个 2 RTT,串行 = 20 RTT = 2000ms - 总计 = 22 RTT = 2200ms - 若浏览器开 5 条并行连接获取图片:10/5 = 2 轮,每轮 2 RTT → 4 RTT = 400ms - 总计 = 2 + 4 = 6 RTT = 600ms
持续连接(HTTP/1.1,无流水线): - TCP 握手:1 RTT - 获取 HTML:1 RTT - 10 个图片串行获取:每个 1 RTT = 10 RTT - 总计 = 12 RTT = 1200ms
持续连接(HTTP/1.1,有流水线): - TCP 握手:1 RTT - 获取 HTML:1 RTT - 10 个图片:解析完 HTML 后连续发出 10 个请求,只需等 1 RTT 收到全部响应 - 总计 = 3 RTT = 300ms
HTTP 报文格式
请求报文
1 | GET /somedir/page.html HTTP/1.1\r\n |
- 请求行(request line):方法、URL、HTTP 版本
- 首部行(header lines):Host、Connection、User-agent 等
- 实体主体(entity body):GET 方法为空,POST 方法包含表单数据
HTTP 请求方法:
| 方法 | 说明 |
|---|---|
| GET | 请求对象 |
| POST | 向服务器提交表单数据(在实体主体中) |
| HEAD | 类似 GET,但服务器不返回请求对象(用于调试) |
| PUT | 将实体体中的内容上传到指定 URL |
| DELETE | 删除指定 URL 上的对象 |
GET 与 POST 提交表单数据的区别:
- GET 方式:表单数据附在 URL 中(
?key1=val1&key2=val2),在请求行中可见,长度受限 - POST 方式:表单数据放在实体主体中,不在 URL 中显示,可以传输大量数据
e.g.: 用户在搜索框中输入 “network”
GET 方式:
GET /search?q=network&lang=zh HTTP/1.1POST 方式:请求行为
POST /search HTTP/1.1,实体主体中包含q=network&lang=zh
响应报文
1 | HTTP/1.1 200 OK\r\n |
常见状态码:
| 状态码 | 含义 |
|---|---|
| 1xx | 信息性 |
| 100 Continue | 服务器已收到请求首部,客户可以继续发送请求体 |
| 2xx | 成功 |
| 200 OK | 请求成功,信息在响应报文中返回 |
| 206 Partial Content | 范围请求成功(用于断点续传) |
| 3xx | 重定向 |
| 301 Moved Permanently | 对象被永久转移,新 URL 在 Location 首部 |
| 302 Found | 对象被临时转移(浏览器自动跳转到 Location) |
| 304 Not Modified | 缓存的副本仍有效(配合条件 GET 使用) |
| 4xx | 客户端错误 |
| 400 Bad Request | 服务器不能理解该请求 |
| 403 Forbidden | 服务器拒绝请求(权限不足) |
| 404 Not Found | 请求的文档不在服务器上 |
| 5xx | 服务器错误 |
| 500 Internal Server Error | 服务器内部错误 |
| 503 Service Unavailable | 服务器暂时无法处理请求(过载或维护) |
| 505 HTTP Version Not Supported | 服务器不支持该 HTTP 协议版本 |
Cookie
HTTP 是无状态的,但很多场景需要标识用户。Cookie 技术有四个组件:
- HTTP 响应报文中的
Set-cookie首部行 - HTTP 请求报文中的
cookie首部行 - 用户端系统中保留的 cookie 文件(由浏览器管理)
- Web 站点的后端数据库
工作流程:
- 用户首次访问站点,服务器创建唯一标识号,在响应中包含
Set-cookie: 1678 - 浏览器将 cookie 存储
- 后续请求自动附带
Cookie: 1678 - 服务器根据 cookie 值查询数据库获取用户状态
e.g.: Cookie 交互过程
1
2
3
4
5
6
7
8
9
10
11
12
13 第一次请求(用户未登录):
GET /index.html HTTP/1.1
Host: www.amazon.com
服务器响应:
HTTP/1.1 200 OK
Set-cookie: session_id=1678; Expires=Wed, 09 Jun 2026 10:18:14 GMT; Path=/; Secure
(页面内容)
第二次请求(浏览器自动附带 cookie):
GET /cart.html HTTP/1.1
Host: www.amazon.com
Cookie: session_id=1678服务器通过 cookie 值
1678查找数据库,识别用户身份并返回个性化内容
Cookie 的用途:用户身份标识、购物车、推荐系统、用户会话状态(Web e-mail)
Cookie 与隐私:Cookie 允许站点追踪用户行为,第三方 Cookie(如广告商)可以跨站点追踪
Web 缓存(代理服务器)
Web 缓存器(Web cache / proxy server):代表初始 Web 服务器来满足 HTTP 请求的网络实体
工作原理:
- 浏览器建立到 Web 缓存器的 TCP 连接,发送 HTTP 请求
- 缓存器检查是否有该对象的缓存副本
- 有 → 直接返回;无 → 向初始服务器请求,收到后存储并返回给客户
优点:
- 减少客户请求的响应时间(尤其是客户与初始服务器之间的瓶颈带宽远低于客户与缓存器之间的带宽时)
- 减少机构接入链路上的流量
- 从整体上减少因特网上的 Web 流量
e.g.: 定量分析
假设:平均对象大小 100 KB,浏览器平均请求速率 15 次/秒,机构接入链路带宽 1.54 Mbps,从初始服务器到路由器的延迟 2 秒
接入链路上的流量强度:\(\frac{15 \times 100 \times 8 \text{ Kb}}{1.54 \text{ Mbps}} = \frac{12 \text{ Mbps}}{1.54 \text{ Mbps}} \approx 0.78\)
此时排队延迟很大,总延迟可能达到数秒
方案1:升级接入链路到 154 Mbps → 流量强度降至 0.0078,延迟约 2 秒,但成本高
方案2:安装 Web 缓存器,假设命中率 0.4
- 40% 请求由缓存满足(延迟约 10 ms)
- 60% 请求仍需通过接入链路(流量强度降至 \(0.6 \times 0.78 = 0.47\))
平均延迟 \(\approx 0.4 \times 0.01 + 0.6 \times 2.01 \approx 1.21\) 秒,远优于不用缓存的情况
条件 GET(conditional GET):用于验证缓存对象是否是最新的
请求中包含 If-Modified-Since 首部行,如果对象未修改,服务器返回 304 Not Modified(不包含对象)
e.g.: 条件 GET 的工作过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 步骤1:缓存器首次请求对象
GET /fruit/kiwi.gif HTTP/1.1
Host: www.exotiquecuisine.com
服务器响应(缓存器存储对象和日期):
HTTP/1.1 200 OK
Date: Sat, 3 Oct 2025 15:39:29
Last-Modified: Wed, 9 Sep 2025 09:23:24
(对象数据)
步骤2:一周后用户再次请求该对象,缓存器发起条件 GET
GET /fruit/kiwi.gif HTTP/1.1
Host: www.exotiquecuisine.com
If-Modified-Since: Wed, 9 Sep 2025 09:23:24
若对象未修改,服务器响应(不含对象,节省带宽):
HTTP/1.1 304 Not Modified
Date: Sat, 10 Oct 2025 15:39:29
若对象已修改,服务器返回 200 OK 和新对象
HTTP/1.1 流水线
HTTP/1.1 支持流水线(pipelining):客户可以在收到前一个请求的响应之前发出下一个请求
但响应必须按请求顺序返回 → 仍存在 HOL 阻塞:一个大对象的响应会阻塞后续所有响应
实际中大多数浏览器通过打开多条并行 TCP 连接来缓解
HTTP/2
HTTP/1.1 的问题:队头阻塞(Head-of-Line blocking, HOL blocking)—— 大对象会阻塞后续小对象的发送
e.g.: HTTP/1.1 的 HOL 阻塞
客户请求一个大视频文件(对象1)和一个小 CSS 文件(对象2)
HTTP/1.1 要求响应按请求顺序返回,服务器必须先发完大视频,才能发送小 CSS
1
2
3
4 客户 ---- 请求对象1(大) ----> 服务器
客户 ---- 请求对象2(小) ----> 服务器
客户 <---- 对象1数据....... -- 服务器 (很长时间)
客户 <---- 对象2数据 -------- 服务器 (被阻塞,等对象1发完)小 CSS 文件被大视频文件”挡住”了,用户感知到页面加载缓慢
HTTP/2 的改进:
- 二进制分帧层:将 HTTP 报文分解为独立的帧(frame),帧是 HTTP/2 通信的最小单位
- HEADERS 帧:携带请求/响应首部
- DATA 帧:携带报文体数据
- 帧可以交错发送,在另一端根据流 ID 重新组装
- 流(stream):一个 TCP 连接中的独立双向字节流序列,每个请求-响应对构成一个流,用流 ID 标识
- 请求响应多路复用:在单一 TCP 连接上并行交错发送多个流的帧,解决 HTTP/1.1 的 HOL 阻塞
- 服务器推送:服务器可以对一个客户请求发送多个响应(主动推送客户没有请求的对象,如 CSS、JS)
- 请求优先级:客户可以为每个流指定优先级和依赖关系,服务器据此调整帧的发送顺序
- 首部压缩(HPACK):减少首部冗余,因为多个请求往往有大量重复的首部字段
e.g.: HTTP/2 的帧交错传输
同样请求大视频(流1)和小 CSS(流2),HTTP/2 将响应分成多个帧交错发送:
1
2 服务器发送的帧序列(单条 TCP 连接):
[流1-HEADERS] [流2-HEADERS] [流1-DATA-1] [流2-DATA-1] [流1-DATA-2] [流2-DATA-2(完)] [流1-DATA-3] ...小 CSS 文件的帧可以穿插在大视频文件的帧之间发送,客户很快就能收到完整的 CSS 文件并开始渲染页面
e.g.: HTTP/2 服务器推送
客户请求
index.html,服务器知道该页面引用了style.css和app.js
1
2
3
4 客户 ---- GET /index.html ----> 服务器
客户 <---- index.html --------- 服务器
客户 <---- PUSH style.css ----- 服务器 (主动推送,客户没有请求)
客户 <---- PUSH app.js -------- 服务器 (主动推送)客户不需要解析 HTML 后再发请求,节省了额外的 RTT
HTTP/3 与 QUIC
HTTP/2 的问题:底层仍使用 TCP,TCP 层的丢包恢复机制会阻塞所有流(TCP 层不知道应用层的流概念)
QUIC(Quick UDP Internet Connections)协议:
- 运行在 UDP 之上
- 自身在传输层实现可靠性、拥塞控制和加密
- 连接建立:将加密握手(类似 TLS)与传输握手合并,只需 1 个 RTT 即可完成连接建立(TCP+TLS 需要 2~3 个 RTT);对之前连接过的服务器甚至可以 0-RTT 恢复
- 独立的流级差错恢复:一个流的丢包不会阻塞其他流,真正解决了 HOL 阻塞
- 连接迁移:使用连接 ID 而非四元组标识连接,客户 IP 变化(如 WiFi 切换到蜂窝)后连接不中断
HTTP/3 = HTTP 语义 + QUIC 传输
e.g.: HTTP/2 仍存在的 HOL 阻塞 vs HTTP/3 的解决
HTTP/2 的多个流共享一条 TCP 连接。当 TCP 层检测到丢包时,TCP 的可靠性机制会暂停整条连接的数据交付,直到丢失的数据被重传——即使丢失的数据只属于某一个流,其他流也被阻塞
1
2
3
4
5 HTTP/2 (TCP):
流1的帧丢失 → TCP 等待重传 → 流2、流3 的帧虽已到达但不能交付(TCP 按序交付)
HTTP/3 (QUIC):
流1的帧丢失 → 仅流1 等待重传 → 流2、流3 的帧正常交付(各流独立)
HTTP 版本对比:
| 特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|---|
| 连接 | 非持续 | 持续 | 持续(单连接) | 持续(单连接) |
| 多路复用 | 无 | 流水线(有序) | 帧交错(乱序) | 帧交错(乱序) |
| HOL 阻塞 | 有 | 有 | 应用层解决,TCP 层仍有 | 完全解决 |
| 首部格式 | 文本 | 文本 | 二进制(HPACK 压缩) | 二进制(QPACK 压缩) |
| 传输层 | TCP | TCP | TCP | UDP(QUIC) |
| 加密 | 可选 | 可选 | 事实上要求 TLS | 内置加密 |
| 连接建立 | 2 RTT(TCP+请求) | 复用 | 1 RTT(TCP+TLS) | 1 RTT(首次),0 RTT(恢复) |
FTP
文件传输协议(File Transfer Protocol)
- 客户-服务器模型
- 使用 TCP
- FTP 使用两条并行的 TCP 连接:
- 控制连接(端口 21):传输控制信息(用户名、密码、命令),持续整个会话
- 数据连接(端口 20):传输文件数据,每次传输文件时建立新的数据连接
这种将控制信息和数据分开传输的方式称为带外(out-of-band)传送
FTP 常用命令:
| 命令 | 说明 |
|---|---|
USER username | 发送用户名 |
PASS password | 发送密码 |
LIST | 请求服务器列出目录下的文件 |
RETR filename | 获取(get)远程主机上的文件 |
STOR filename | 存放(put)文件到远程主机 |
FTP 常见返回码:
| 返回码 | 含义 |
|---|---|
| 331 | 用户名OK,等待密码 |
| 125 | 数据连接已打开,开始传输 |
| 425 | 无法打开数据连接 |
| 452 | 写文件错误 |
FTP 的两种数据连接模式:
- 主动模式(Active Mode):客户在控制连接上用
PORT命令告诉服务器自己的 IP 和端口,服务器主动从端口 20 发起到客户的数据连接 - 被动模式(Passive Mode):客户发送
PASV命令,服务器回复一个临时端口号,客户主动连接到该端口。适用于客户在 NAT/防火墙后面的场景(服务器无法主动连接客户)
FTP 是有状态的:服务器需要记住用户的当前目录、已认证的账户等
电子邮件
因特网电子邮件系统的三个组成部分:
- 用户代理(user agent):编写、阅读邮件(如 Outlook、Thunderbird)
- 邮件服务器(mail server):包含用户的邮箱和外出报文的消息队列
- 简单邮件传输协议(SMTP)
SMTP
SMTP 使用 TCP 在客户和服务器之间传输邮件,端口 25
特点:
- 使用持续连接
- 要求报文(首部和体)用 7 位 ASCII 编码
- 是一个推协议(push protocol):发送方的邮件服务器将文件推向接收方的邮件服务器
SMTP 交互过程:
1 | S: 220 hamburger.edu |
SMTP 与 HTTP 的比较:
| HTTP | SMTP | |
|---|---|---|
| 方向 | 拉协议(pull) | 推协议(push) |
| 编码 | 不要求 ASCII | 要求 7 位 ASCII |
| 多对象 | 每个对象封装在独立响应中 | 所有对象放在同一报文中 |
邮件报文格式与邮件访问协议
邮件报文首部(不同于 SMTP 命令):
1 | From: alice@crepes.fr |
SMTP 中的 MAIL FROM 是 SMTP 握手协议的一部分,而邮件正文中的 From: 只是报文正文的一部分,两者可以不一致
e.g.: Alice(alice@a.com)向 Bob(bob@b.com)发送邮件的完整路径
- Alice 用邮件客户端(用户代理)撰写邮件,点击发送
- 用户代理通过 SMTP(或 HTTP)将邮件发送到 Alice 的邮件服务器
mail.a.com- 邮件进入
mail.a.com的外出报文队列mail.a.com的 SMTP 客户端与 Bob 的邮件服务器mail.b.com建立 TCP 连接(端口 25)- 通过 SMTP 协议将邮件推送到
mail.b.commail.b.com将邮件放入 Bob 的邮箱- Bob 使用邮件客户端通过 POP3/IMAP(或 HTTP)从
mail.b.com取回邮件关键:发送方到发送方邮件服务器用 SMTP/HTTP,邮件服务器之间用 SMTP,接收方从接收方邮件服务器取邮件用 POP3/IMAP/HTTP
MIME 扩展
SMTP 要求报文用 7 位 ASCII 编码,无法直接传输二进制数据(图片、音频等)和非 ASCII 文字
MIME(Multipurpose Internet Mail Extensions)通过在邮件首部添加额外行来描述报文体的编码方式:
1 | MIME-Version: 1.0 |
Content-Type:描述报文体的类型(text/plain,image/jpeg,multipart/mixed等)Content-Transfer-Encoding:描述编码方式(base64将二进制编码为 ASCII)multipart:允许一封邮件包含多个部分(文本 + 附件)
邮件访问协议
SMTP 是推协议,用于将邮件从发送方传到接收方邮件服务器。用户从邮件服务器读取邮件时需要拉协议:
- POP3(Post Office Protocol - Version 3):端口 110
- 授权阶段:用户名和密码
- 事务处理阶段:取回、删除、标记邮件
- 更新阶段:结束 POP3 会话,删除标记的邮件
- “下载并删除”模式:换了设备就看不到了
- “下载并保留”模式:多设备可以看到
- POP3 是无状态的(跨会话不保持状态)
e.g.: POP3 协议交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 授权阶段:
C: user bob
S: +OK
C: pass hungry
S: +OK user successfully logged on
事务处理阶段:
C: list
S: 1 498
S: 2 912
S: .
C: retr 1
S: (邮件1的内容)
S: .
C: dele 1
S: +OK message 1 deleted
C: retr 2
S: (邮件2的内容)
S: .
C: dele 2
S: +OK message 2 deleted
C: quit
S: +OK POP3 server signing off
- IMAP(Internet Mail Access Protocol):端口 143
- 将所有邮件保存在服务器上
- 允许用户将邮件组织在远程文件夹中
- 跨会话保持状态(文件夹名称、报文与文件夹的映射等)
- 允许用户获取报文的某些部分(如只读取首部,或多部分 MIME 的某一部分)
- IMAP 是有状态的
POP3 vs IMAP:
| POP3 | IMAP | |
|---|---|---|
| 邮件存储 | 下载到本地 | 保留在服务器 |
| 远程文件夹 | 不支持 | 支持 |
| 跨设备同步 | 差(下载后服务器无邮件) | 好(所有设备看到相同状态) |
| 部分读取 | 不支持 | 支持(如只读首部) |
| 状态 | 无状态 | 有状态 |
| 复杂度 | 简单 | 复杂 |
- 基于 Web 的电子邮件(如 Gmail)
- 用户代理就是浏览器
- 用户与邮件服务器之间使用 HTTP
- 邮件服务器之间仍使用 SMTP
DNS
域名系统(Domain Name System)
DNS 提供的服务:
- 主机名到 IP 地址的转换(核心功能)
- 主机别名(host aliasing):一个复杂规范主机名可以有多个简单别名
- 邮件服务器别名(mail server aliasing)
- 负载分配(load distribution):一个域名对应多个 IP 地址,DNS 轮转返回
DNS 的层次结构
DNS 是一个分布式数据库,使用层次化的服务器实现
1 | 根DNS服务器 |
- 根 DNS 服务器:全球 13 组(标号 A 到 M),通过任播技术实际有数百个分布式副本
- 顶级域(TLD)DNS 服务器:负责 com、org、net、edu 等顶级域以及各国家顶级域(如 cn、uk)
- 权威 DNS 服务器:组织机构自己的 DNS 服务器,提供该组织内主机名到 IP 地址的映射
域与区域的区别:
- 域(domain):域名空间中的一个子树,如
example.com及其所有子域 - 区域(zone):DNS 管理的基本单位,一个区域是域名空间中由单个权威 DNS 服务器管理的连续部分。一个域可以被划分为多个区域(如
example.com可以将sub.example.com委托给另一个区域)
每个区域有自己的权威名字服务器,该服务器持有该区域内所有主机的权威记录
本地 DNS 服务器(local DNS server):
- 不严格属于 DNS 层次结构
- 每个 ISP 都有一个
- 主机发起 DNS 查询时,查询先发往本地 DNS 服务器,起到代理的作用
DNS 查询方式
递归查询(recursive query):请求的主机将查询任务交给本地DNS服务器,由它代为完成整个查询过程
迭代查询(iterative query):本地DNS服务器依次询问根、TLD、权威服务器,每个被询问的服务器回复”你去问谁”
实际中常用的模式:从请求主机到本地 DNS 服务器是递归查询,本地 DNS 服务器向其他 DNS 服务器做迭代查询
e.g.: 用户在浏览器中输入
www.example.com,本地 DNS 服务器无缓存
- 主机向本地 DNS 服务器发送查询
www.example.com(递归)- 本地 DNS → 根 DNS 服务器:查询
www.example.com- 根 DNS 回复:我不知道,但
.com的 TLD 服务器是ns1.com,其 IP 是x.x.x.x(NS + A 记录)- 本地 DNS → TLD 服务器
ns1.com:查询www.example.com- TLD 服务器回复:
example.com的权威 DNS 是dns.example.com,IP 是y.y.y.y- 本地 DNS → 权威 DNS
dns.example.com:查询www.example.com- 权威 DNS 回复:
www.example.com的 A 记录是93.184.216.34- 本地 DNS 将结果返回给主机,并缓存该记录(TTL 时间内有效)
共 8 条 DNS 报文(4 次查询 + 4 次回答),涉及 4 次 RTT(不含主机到本地 DNS 的 RTT 则为 3 次)
DNS 缓存
当DNS服务器收到一个DNS回答时,它可以将该回答中的信息缓存在本地存储器中
缓存条目在一段时间后过期(TTL,Time-To-Live)
本地 DNS 服务器可以缓存 TLD 服务器的 IP 地址,因此根 DNS 服务器实际很少被访问
DNS 记录和报文
DNS 分布式数据库中存储资源记录(Resource Record, RR)
RR 是一个四元组:(Name, Value, Type, TTL)
| Type | Name | Value | 说明 |
|---|---|---|---|
| A | 主机名 | IP 地址 | 主机名到 IPv4 地址的映射 |
| AAAA | 主机名 | IPv6 地址 | 主机名到 IPv6 地址的映射 |
| NS | 域 | 权威 DNS 服务器主机名 | 知道如何获得该域中主机 IP 地址的 DNS 服务器 |
| CNAME | 别名 | 规范主机名 | 将别名映射到规范主机名 |
| MX | 别名 | 邮件服务器规范名 | 邮件服务器别名到规范名的映射 |
DNS 报文
DNS 查询和回答报文格式相同:
1 | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |
- 标识(16 bit):查询和回答使用相同标识,用于匹配
- 标志:
- QR:0 = 查询,1 = 回答
- AA:权威回答
- TC:报文被截断
- RD:期望递归
- RA:递归可用
- 问题区域:查询的名字和类型
- 回答区域:对查询的回答(资源记录)
- 权威区域:其他权威服务器的记录
- 附加区域:其他有用的记录(如 NS 记录对应的 A 记录,称为”胶水记录”)
向 DNS 数据库中插入记录
向域名注册机构注册域名时,需要提供:
- 权威 DNS 服务器的名字和 IP 地址
- 注册机构将 NS 记录和对应的 A 记录插入 TLD 服务器
之后在自己的权威 DNS 服务器上添加需要的 A 记录、MX 记录等
e.g.: 注册域名
networkutopia.com
- 向域名注册机构(如 GoDaddy)提供:
- 权威 DNS 服务器名:
dns1.networkutopia.com- 权威 DNS 服务器 IP:
212.212.212.1- 注册机构在
.comTLD 服务器中插入:
(networkutopia.com, dns1.networkutopia.com, NS)(dns1.networkutopia.com, 212.212.212.1, A)- 在自己的权威 DNS 服务器
dns1.networkutopia.com上配置:
(www.networkutopia.com, 212.212.212.4, A)—— Web 服务器(networkutopia.com, mail.networkutopia.com, MX)—— 邮件服务器(mail.networkutopia.com, 212.212.212.5, A)—— 邮件服务器 IP
DNS 安全
DDoS 带宽洪泛攻击:向根 DNS 服务器或 TLD 服务器发送大量查询,目前通过分组过滤和根服务器的本地 DNS 缓存来缓解
中间人攻击:截获 DNS 查询并返回伪造回答
DNS 放大攻击:向多个 DNS 服务器发送查询(源 IP 伪造为攻击目标),利用 DNS 回答比查询大得多的特点放大流量
P2P 应用
经典 P2P 架构
Napster(集中式目录):
- 中心服务器维护文件位置的索引
- 对等方在中心服务器注册自己拥有的文件
- 查询时向中心服务器请求 → 服务器返回拥有该文件的对等方列表 → 直接从对等方下载
- 问题:中心服务器是单点故障,也是版权诉讼的目标
Gnutella(完全分散式):
- 无中心服务器,完全分布式
- 使用洪泛查询(flooding query):查询报文在覆盖网络(overlay network)上洪泛传播
- 每个对等方向邻居转发查询(Query),若匹配则沿原路返回结果(QueryHit)
- 使用 TTL 限制洪泛范围
- 问题:查询开销大,难以保证找到稀有文件
KaZaA(混合式):
- 介于 Napster 和 Gnutella 之间
- 对等方被组织为组,每个组有一个组长(super peer / group leader)
- 组长维护组内所有对等方的文件列表
- 查询先发给组长,组长之间再相互查询
- 兼具集中式查询效率和分布式的健壮性
BitTorrent
BitTorrent 是用于文件分发的流行 P2P 协议
- 洪流(torrent):参与一个特定文件分发的所有对等方的集合
- 追踪器(tracker):跟踪参与洪流的对等方
- 文件被划分为等长的块(chunk),典型大小 256KB
工作机制:
- 新对等方加入洪流,向追踪器注册并获得对等方子集列表
- 与这些对等方建立 TCP 连接(邻近对等方)
- 周期性询问邻近对等方拥有哪些块
- 使用最稀缺优先(rarest first)策略请求块:优先请求在邻近对等方中副本数最少的块
- 发送策略:一报还一报(tit-for-tat)
- 每 10 秒重新计算,向当前给自己提供数据速率最高的 4 个对等方发送数据(疏通,unchoke)
- 每 30 秒随机选择一个额外对等方发送数据(优化疏通,optimistically unchoke),探索是否有更好的交易伙伴
P2P 文件分发的效率
客户-服务器体系结构分发 \(F\) 比特文件给 \(N\) 个对等方的时间下界:
\[D_{cs} \ge \max\left\{\frac{NF}{u_s},\ \frac{F}{d_{min}}\right\}\]
其中 \(u_s\) 为服务器上传速率,\(d_{min}\) 为最小客户下载速率
P2P 体系结构的时间下界:
\[D_{P2P} \ge \max\left\{\frac{F}{u_s},\ \frac{F}{d_{min}},\ \frac{NF}{u_s + \sum_{i=1}^{N}u_i}\right\}\]
当 \(N\) 很大时,P2P 的分发时间接近常数(自扩展性),而客户-服务器的分发时间线性增长
e.g.: 文件大小 \(F = 15\) Gb,服务器上传速率 \(u_s = 30\) Mbps,每个客户下载 \(d_i = 2\) Mbps,上传 \(u_i = 300\) kbps,\(N = 1000\) 个客户
客户-服务器:
\[D_{cs} \ge \max\left\{\frac{1000 \times 15 \text{Gb}}{30 \text{Mbps}},\ \frac{15 \text{Gb}}{2 \text{Mbps}}\right\} = \max\{500000s,\ 7500s\} \approx 5.8 \text{ 天}\]
瓶颈在服务器上传带宽,服务器需要发送 \(N\) 份文件
P2P:
\[D_{P2P} \ge \max\left\{\frac{15 \text{Gb}}{30 \text{Mbps}},\ \frac{15 \text{Gb}}{2 \text{Mbps}},\ \frac{1000 \times 15 \text{Gb}}{30 \text{Mbps} + 1000 \times 300 \text{kbps}}\right\}\]
\[= \max\{500s,\ 7500s,\ \frac{15 \times 10^9}{330 \times 10^6} \approx 45455s\} \approx 12.6 \text{ 小时}\]
P2P 比 C/S 快约 11 倍,因为所有对等方的上传带宽都被利用
分布式散列表(DHT)
DHT(Distributed Hash Table):P2P 网络中的分布式数据库
每个对等方只持有键值对的一个小子集,任何对等方可以用特定的键来查询该数据库
环形 DHT:
- 将所有对等方组织成一个环(按标识符排序)
- 每个键分配给标识符最接近(顺时针方向最近的)的对等方
- 每个对等方只知道直接后继和直接前驱
查询方式:
- 简单:沿环顺序转发查询,\(O(N)\) 条报文
- 捷径(shortcuts):每个对等方额外维护若干快捷链接(如 Chord 协议中的指针表),查询复杂度降低到 \(O(\log N)\)
对等方的加入和离开:
- 加入时:从环中分担一部分键值对
- 离开时:将键值对转交给后继
e.g.: 环形 DHT 查询
对等方标识符空间为 0~15,当前有对等方 1, 3, 4, 5, 8, 10, 12, 15
每个键被分配给顺时针方向第一个标识符 ≥ 键值的对等方(最近后继)
键 分配给对等方 2 3 7 8 11 12 15 15 0 1 对等方 1 要查询键 11:
- 无捷径:\(1 \to 3 \to 4 \to 5 \to 8 \to 10 \to 12\)(6 次转发),\(O(N)\)
- 有捷径(每个节点维护到 \(+1,+2,+4,+8\) 位置的指针):\(1 \to 8 \to 12\)(2 次转发),\(O(\log N)\)
视频流和内容分发网
因特网视频
视频:以恒定速率展示的图像序列
数字化视频的特点:
- 可以被压缩,用比特率衡量质量
- 压缩方式:空间冗余(图像内)和时间冗余(相邻图像间)
- CBR(恒定比特率)vs VBR(可变比特率)
HTTP 流和 DASH
简单 HTTP 流:视频作为一个 HTTP 对象存储在服务器上,客户端通过 HTTP GET 请求获取并缓冲在客户端应用缓存中
缺点:所有客户收到相同编码的视频,不能适应不同的带宽条件
DASH(Dynamic Adaptive Streaming over HTTP,经 HTTP 的动态自适应流):
- 视频编码为不同质量级别的多个版本,存储在 HTTP 服务器上
- 每个版本有不同的比特率和对应的 URL,记录在一个告示文件(manifest file)中
- 客户端动态请求不同版本的视频块,根据当前可用带宽自适应选择质量级别
- 智能在客户端:客户自主决定何时请求块、请求哪个质量级别、从哪个服务器请求
e.g.: DASH 自适应过程
视频被分成 4 秒一段的块,服务器提供三种质量版本:
版本 比特率 分辨率 低质量 500 kbps 480p 中质量 1.5 Mbps 720p 高质量 4 Mbps 1080p
1
2
3
4 时刻0: 带宽 5 Mbps → 客户请求高质量块1 (1080p)
时刻4s: 带宽 5 Mbps → 客户请求高质量块2 (1080p)
时刻8s: 带宽降至 1 Mbps → 客户请求低质量块3 (480p)
时刻12s: 带宽恢复 3 Mbps → 客户请求中质量块4 (720p)客户端连续监测可用带宽,自适应切换质量级别,避免缓冲中断
内容分发网(CDN)
CDN(Content Distribution Network):在多个地理分布的位置存储内容的副本,将用户请求导向最近或最优的 CDN 节点
CDN 服务器部署策略:
- 深入(Enter Deep):将 CDN 服务器部署到接入 ISP 中,靠近用户,减少延迟和丢包,但维护成本高
- 邀请做客(Bring Home):在少量关键位置建造大型集群,通常在 IXP 附近,维护简单但延迟稍高
CDN 操作过程(通常基于 DNS):
- 用户访问某个 URL
- 该域名的权威 DNS 服务器返回 CDN 域名的 CNAME
- 用户的本地 DNS 服务器向 CDN 的 DNS 系统发起查询
- CDN 的 DNS 系统根据用户位置和服务器负载等因素,返回最优 CDN 节点的 IP
- 用户与该 CDN 节点建立 TCP 连接并获取内容
e.g.: 用户 Bob 在上海访问
video.netcinema.com/6Y7B23V
1
2
3
4
5
6
7
8
9
10 1. Bob 的主机查询 DNS: video.netcinema.com
2. Bob 的本地 DNS 服务器 → netcinema 的权威 DNS
回复: video.netcinema.com 的 CNAME 是 a]024.cdn.com
3. Bob 的本地 DNS 服务器 → CDN 权威 DNS (cdn.com)
CDN 的 DNS 根据 Bob 本地 DNS 的 IP 地址推断 Bob 在上海
回复: a1024.cdn.com 的 A 记录为 218.75.x.x(上海 CDN 节点)
4. Bob 的浏览器与 218.75.x.x 建立 TCP 连接
5. 发送 HTTP GET 请求获取视频内容
若该 CDN 节点有缓存 → 直接返回
若无缓存 → CDN 节点从源站获取、缓存后返回关键:CDN 的 DNS 系统通过观察本地 DNS 服务器的 IP 来推断用户位置,选择最优节点
CDN 集群选择策略:
- 地理上最近(geographically closest):根据本地 DNS 服务器的 IP 地址推断用户位置,选择地理上最近的集群。简单但不总是最优(地理近不等于网络近)
- 实时测量(real-time measurements):CDN 周期性地向各集群发送探测(如 ping、DNS 查询),根据实际延迟和丢包率选择最优集群
套接字编程
UDP 套接字编程
UDP:客户与服务器之间没有连接
- 发送方在每个分组中明确指明目的 IP 地址和端口号
- 服务器从接收到的分组中提取发送方的 IP 地址和端口号
Python UDP 客户端:
1 | from socket import * |
Python UDP 服务器:
1 | from socket import * |
TCP 套接字编程
TCP:客户必须先与服务器建立连接
- 服务器进程必须先运行,创建欢迎套接字(welcoming socket)
- 客户创建本地套接字,指定服务器 IP 和端口号,发起连接
- 服务器收到连接请求后,创建专用于该客户的新的连接套接字(connection socket)
Python TCP 客户端:
1 | from socket import * |
Python TCP 服务器:
1 | from socket import * |
UDP 与 TCP 套接字的关键区别:
| UDP | TCP | |
|---|---|---|
| 套接字类型 | SOCK_DGRAM | SOCK_STREAM |
| 连接建立 | 无需连接 | 需要先 connect/accept |
| 发送方式 | sendto(每次指定地址) | send(连接建立后无需指定) |
| 服务器 | 一个套接字服务所有客户 | 每个客户一个连接套接字 |
小结
应用层是协议栈中最靠近用户的一层:
- 网络应用体系结构:客户-服务器(固定服务器 + 动态客户)vs P2P(自扩展性)
- 进程通信:通过套接字(Socket)——应用层与传输层的接口,进程用 IP + 端口号标识
- HTTP:无状态的请求-响应协议
- 1.0:非持续连接(每个对象 2 RTT)
- 1.1:持续连接 + 流水线(HOL 阻塞,多条并行 TCP 缓解)
- 2.0:二进制分帧 + 多路复用 + 服务器推送 + 首部压缩(应用层 HOL 解决,TCP 层仍有)
- 3.0:基于 QUIC(UDP),0/1-RTT 连接建立,流级差错恢复,完全解决 HOL 阻塞
- Cookie:使无状态的 HTTP 能够跟踪用户状态
- Web 缓存:代理服务器减少响应时间和链路流量,条件 GET 验证缓存有效性
- FTP:双 TCP 连接(控制 + 数据),带外传送,有状态
- 电子邮件:SMTP(推协议,端口 25,7 位 ASCII)+ POP3(简单拉)/ IMAP(功能丰富拉),MIME 扩展支持二进制
- DNS:分布式层次数据库(根→TLD→权威),递归/迭代查询,RR 类型(A, AAAA, NS, CNAME, MX),缓存 + TTL
- P2P:Napster(集中索引)→ Gnutella(洪泛查询)→ KaZaA(混合式),BitTorrent 的最稀缺优先和一报还一报,DHT 的 \(O(\log N)\) 查询
- 视频流:DASH 自适应比特率选择
- CDN:通过 DNS 重定向将用户导向最优服务器,深入(接入ISP)vs 邀请做客(IXP)
- 套接字编程:UDP(SOCK_DGRAM,无连接,sendto)vs TCP(SOCK_STREAM,面向连接,欢迎套接字 + 连接套接字)