COMP5416 Week 04 DNS 与 P2P 讲课总结

COMP5416 Week 04 讲课总结:DNS 与 P2P

课程:COMP5416/COMP4416 — Advanced Network Technologies,Semester 2 2026 讲师:Professor Vincent Gramoli 讲义:W4-DSN-P2P.pdf(48 页) 教材:Kurose & Ross 9th ed. —— 第 2 章,2.4 / 2.5 / 2.6 节

⚠️ Midterm quiz 在 Week 6,20 道选择题,占 20%。 ✅ 老师已说明:期中不考 Week 6 的内容,范围就是 Week 1–5。

本讲三大块:DNS → 套接字编程 → P2P(含 DHT)。 文件分发时间公式和 DHT 后继节点是最可能出计算题的地方。


第一部分:DNS

一、为什么需要 DNS

两套标识体系

互联网主机和路由器同时有两种标识:

标识 长度 用途 谁在用
IP 地址 32 位(IPv4) 用于给数据报寻址 机器
名字 可变 如 www.yahoo.com 人

讲义的类比:人也有很多标识 —— 姓名、护照号。 姓名给人叫,护照号给系统查 —— 和「域名 vs IP」是同一回事。

DNS = Domain Name System,它同时是两样东西:

  1. 一个分布式数据库,实现在许多名字服务器的层级结构中
  2. 一个应用层协议 —— 主机与名字服务器通信以完成名字解析

二、为什么不用集中式 DNS(高频 MCQ)

理由 说明
单点故障 single point of failure —— 那台服务器挂了整个互联网就瘫了
距离远 集中式数据库对远处的用户时延高
可扩展性 scalability —— 一台机器扛不住全球查询量

💡 讲义只列了这三条,原书还有第四条「维护量大」(要为全球所有主机维护记录)。 考试记住讲义的三条一定够,但四条都写也不会错。

三、DNS 提供的服务(不止翻译名字)

服务 说明
主机名 → IP 地址翻译 最基本的
主机别名(host aliasing) 规范名(canonical)与别名(alias)
邮件服务器别名 mail server aliasing
负载分配(load distribution) 复制的 Web 服务器:一个名字对应多个 IP 地址

「DNS 可以做负载均衡」是很容易被忽略的考点。 原理:一个域名的 A 记录里放一组 IP,DNS 服务器每次响应时轮换(rotate)返回顺序, 客户通常用第一个,于是流量就被分散到不同服务器上了。

四、DNS 的层级结构

                  Root DNS Servers
/ | \
com DNS org DNS edu DNS ← TLD 服务器
/ \ / \
yahoo.com amazon.com poly.edu umass.edu ← 权威服务器
DNS DNS DNS DNS

解析 www.amazon.com 的一级近似(讲义 p5)

步骤 动作
1 客户查根服务器,找到 com DNS 服务器
2 客户查 .com DNS 服务器,找到 amazon.com DNS 服务器
3 客户查 amazon.com DNS 服务器,拿到 www.amazon.com 的 IP

注意这是「一级近似」 —— 真实过程中间还有本地 DNS 服务器代劳,见第六节。

五、四类 DNS 服务器(必考)

类型 职责 关键细节
Root(根) 层级的顶点 全球 13 个根名字「服务器」(逻辑上 13 个,每个都有大量镜像站点)
TLD(顶级域) 负责 com、org、net、edu、aero、jobs、museums 以及所有国家顶级域(uk、fr、ca、jp) 💡 Network Solutions 维护 .com;Educause 维护 .edu
Authoritative(权威) 组织自己的 DNS 服务器,提供该组织主机的权威名字→IP 映射 可由组织自己维护,也可外包给服务商
Local(本地) 见下节 严格来说不属于这个层级结构!

根服务器的「13 个」是怎么回事

讲义 p6 列出了 a 到 m 共 13 个字母标识的根服务器,分布在 Verisign、USC-ISI、ICANN、NASA、 Internet Software Consortium、Netnod、RIPE、WIDE、Cogent、马里兰大学、ARL、美国国防部等机构。

每一个「服务器」实际上是很多台机器(如 l. 有 41 个站点,j. 有 69 个站点)—— 靠任播(anycast)让用户访问到最近的那台。 「13」这个数字来自早期 UDP 报文大小限制,考试问「有几个根服务器」答 13 即可。

六、本地 DNS 服务器(易考细节)

特性 说明
层级归属 不严格属于该层级结构 —— 这是最容易被考的一点
谁有 每个 ISP(住宅 ISP、公司、大学)都有一个
别名 也叫「默认名字服务器」(default name server)
作用 主机发 DNS 查询时,查询先发给它
缓存 有最近「名字→地址」的本地缓存(⚠️ 但可能过时!)
角色 充当代理(proxy),把查询转发进层级结构

为什么它「不属于层级」:根、TLD、权威三类是有明确从属关系的树形结构, 而本地 DNS 服务器只是你所在网络的一个代理,谁都能架一个(比如 8.8.8.8、1.1.1.1), 它不「拥有」任何域的权威数据。

七、迭代查询 vs 递归查询(必考对照)

场景(讲义 p9–p10):cis.poly.edu 上的主机想要 gaia.cs.umass.edu 的 IP。

迭代查询(Iterated)

机制:被联系的服务器回复「下一个该问谁」的服务器名字。 那句话:「我不知道这个名字,但你去问那台服务器。」

8 条消息的完整流程:

# 方向 内容
1 主机 → 本地 DNS 查询 gaia.cs.umass.edu
2 本地 DNS → 根 查询
3 根 → 本地 DNS 「去问 .edu TLD」
4 本地 DNS → TLD (.edu) 查询
5 TLD → 本地 DNS 「去问 dns.cs.umass.edu」
6 本地 DNS → 权威 查询
7 权威 → 本地 DNS 返回 IP
8 本地 DNS → 主机 返回 IP

本地 DNS 服务器跑了 3 个来回(2-3、4-5、6-7),负担全在它身上。

递归查询(Recursive)

机制:把名字解析的负担交给被联系的名字服务器。 问题:层级上层负载重(heavy load at upper levels)。

8 条消息的完整流程:

# 方向 内容
1 主机 → 本地 DNS 查询
2 本地 DNS → 根 查询
3 根 → TLD 代为查询(查询沿层级下行)
4 TLD → 权威 代为查询
5 权威 → TLD 返回 IP
6 TLD → 根 返回 IP(答案沿层级上行)
7 根 → 本地 DNS 返回 IP
8 本地 DNS → 主机 返回 IP

两者的对比

维度 迭代 递归
消息总数 8(本例) 8(本例)
谁承担往返 本地 DNS 反复跑 层级逐级转发
形状 星形(都以本地 DNS 为中心) 链形(下行查询、上行应答)
上层负载 低 高 —— 根服务器要参与整条链

区分口诀: 迭代 = 服务器给你「指路」,你自己去跑; 递归 = 服务器替你「跑腿」,直接把答案带回来。

实践中的混合用法:主机 → 本地 DNS 通常是递归(主机很懒,只想要答案), 本地 DNS → 层级结构通常是迭代(根服务器不愿意替全世界跑腿)。

八、DNS 缓存与记录更新

要点 说明
谁会缓存 任何名字服务器学到映射后都会缓存它
缓存多久 缓存条目在一段时间后超时消失 —— 这个时间叫 TTL
副作用 缓存条目可能过时 ⇒ DNS 是「尽力而为」的名字→地址翻译
⚠️ 最麻烦的场景 如果主机改了 IP 地址,在所有 TTL 过期之前,全网可能都还不知道
更新机制 RFC 2136(IETF 提案标准)

实践含义:要迁移服务器时,运维会提前几天把 TTL 调小(比如从 86400 秒降到 300 秒), 这样切换当天全网能很快跟上。这是「TTL 决定了变更的传播速度」的直接应用。

九、DNS 资源记录(RR)—— 必考

RR 格式:(name, value, type, ttl)

类型 name 是什么 value 是什么 助记
A 主机名 IP 地址 Address
NS 域名(如 foo.com) 该域权威名字服务器的主机名 Name Server
CNAME 某个「规范(真实)名」的别名 规范名 Canonical NAME
MX 域名 与该名字关联的邮件服务器名字 Mail eXchange

CNAME 的实例(讲义 p12):www.ibm.com 实际上是 servereast.backup2.ibm.com。

四种类型必须能秒答。一句话记忆: A 给 IP;NS 给服务器名;CNAME 给真名;MX 给邮件服务器。

十、往 DNS 里插入记录(讲义 p13)

场景:新创业公司 "Network Utopia"

步骤 动作
1 在 DNS 注册商(如 Network Solutions)注册 networkutopia.com
2 提供权威名字服务器的名字和 IP
3 注册商往 .com TLD 服务器插入两条 RR
4 自己在权威服务器上创建记录

注册商插入 TLD 的两条:

(networkutopia.com, dns1.networkutopia.com, NS)
(dns1.networkutopia.com, 212.212.212.1, A)

自己在权威服务器上创建:

(www.networkutopia.com,      212.212.212.22,        A)
(www.home.networkutopia.com, www.networkutopia.com, CNAME)

「NS + A 成对出现」是常考点: NS 记录只给出服务器的「名字」(dns1.networkutopia.com), 还需要一条 A 记录给出它的「IP」(212.212.212.1),否则拿到名字也联系不上 —— 这就是所谓的「胶水记录(glue record)」。


第二部分:套接字编程

十一、套接字基础

套接字:应用进程与端到端传输协议之间的门。

控制权划分(讲义 p15 的图,考点):

┌─────────────────┐
│ 应用(process) │ ← 应用开发者控制
│ ┌─────────┐ │
│ │ socket │ │ ← 门
│ └────┬────┘ │
├────────┼────────┤
│ 传输层 │ ← 操作系统控制
│ 网络层 │
│ 链路层 │
│ 物理层 │
└─────────────────┘
部分 谁控制
应用层 应用开发者控制
传输层及以下 操作系统控制

考点:开发者唯一能选的传输层参数就是「用 TCP 还是 UDP」以及少数几个选项, 其余(拥塞窗口、重传定时器等)全在内核里,动不了。

两种套接字对应两种传输服务:

套接字类型 传输服务
SOCK_DGRAM UDP:不可靠数据报
SOCK_STREAM TCP:可靠、面向字节流

讲义的示例应用(贯穿 UDP/TCP 两版代码):

  1. 客户从键盘读一行字符,发给服务器
  2. 服务器收到后转成大写
  3. 服务器把改后的数据发回客户
  4. 客户收到并显示

十二、UDP 套接字编程

特点(讲义 p17)

特点 说明
无连接 客户与服务器之间没有「连接」,发数据前无握手
发送方的责任 给每个分组显式附上目的 IP 和端口号
接收方的动作 从收到的分组中提取发送方的 IP 和端口号
可靠性 传输的数据可能丢失或乱序到达

应用视角:UDP 在客户与服务器之间提供「字节组(数据报)」的不可靠传输。

交互流程(讲义 p18)

服务器(运行在 serverIP)                客户
──────────────────────── ────────────────────────
socket(AF_INET, SOCK_DGRAM)
bind(port = x)
│ socket(AF_INET, SOCK_DGRAM)
│ │
recvfrom(serverSocket) ←────────── sendto(serverName, x)
│ │
sendto(clientAddress) ──────────→ recvfrom(clientSocket)
│ │
│ close()

Python 代码要点(讲义 p19–20)

客户端:

from socket import *
clientSocket = socket(AF_INET, SOCK_DGRAM) # 创建 UDP 套接字
message = input('...').encode('utf-8') # 字符串 → 字节
clientSocket.sendto(message, (serverName, serverPort)) # 附上服务器地址+端口
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
print(modifiedMessage.decode('utf-8')) # 字节 → 字符串
clientSocket.close()

服务器端:

serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort)) # 绑定到本地端口
while 1:
message, clientAddress = serverSocket.recvfrom(2048) # 同时拿到客户地址
modified = message.decode('utf-8').upper()
serverSocket.sendto(modified.encode('utf-8'), clientAddress)

三个要注意的细节:

  1. 客户端没有 bind() —— 操作系统自动分配一个临时端口
  2. recvfrom() 返回两样东西:数据 和 发送方地址 —— 这是 UDP 独有的
  3. encode/decode 是 Python 3 的新要求(讲义特意标注了 "New feature in Python 3")

十三、TCP 套接字编程

特点(讲义 p21)

要求 说明
服务器进程必须先运行 客户才能联系它
服务器必须先创建「欢迎套接字」 迎接客户的到来
客户主动发起 创建 TCP 套接字,指定服务器的 IP 和端口
TCP 建立连接 客户 TCP 与服务器 TCP 建立连接

关键机制:服务器的「两个套接字」(极易考)

讲义原文:当被客户联系时,服务器 TCP 会「创建一个新的套接字」 供服务器进程与这个特定客户通信。

好处 说明
允许服务器同时与多个客户对话 每个客户一个专属套接字
区分不同客户靠什么 源端口号(source port numbers)

两个套接字的角色:

套接字 何时创建 作用 何时关闭
serverSocket(欢迎套接字) 启动时 listen() 等待连接请求 不关闭(要一直接客)
connectionSocket(连接套接字) accept() 返回时 与该特定客户通信 通信完关闭它

交互流程(讲义 p22)

服务器(运行在 hostid)                客户
──────────────────────── ────────────────────────
serverSocket = socket()
bind(port = x)
serverSocket.listen(1)
│
connectionSocket = accept() ←──── clientSocket = socket()
(TCP 连接建立) clientSocket.connect((hostid, x))
│ │
recv(connectionSocket) ←───────── send(clientSocket)
│ │
send(connectionSocket) ─────────→ recv(clientSocket)
│ │
close(connectionSocket) close(clientSocket)
(欢迎套接字不关)

Python 代码要点(讲义 p23–24)

客户端:

clientSocket = socket(AF_INET, SOCK_STREAM)     # TCP 套接字
clientSocket.connect((serverName, serverPort)) # 建立连接
clientSocket.send(sentence.encode('utf-8')) # 不需要再指定地址!
modifiedSentence = clientSocket.recv(1024)
clientSocket.close()

服务器端:

serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1) # 开始监听
while 1:
connectionSocket, addr = serverSocket.accept() # 返回「新」套接字
sentence = connectionSocket.recv(1024) # 只读字节,不返回地址
capitalized = sentence.decode('utf-8').upper().encode('utf-8')
connectionSocket.send(capitalized)
connectionSocket.close() # 只关连接套接字

十四、UDP vs TCP 套接字对照(考点汇总)

维度 UDP TCP
socket 类型 SOCK_DGRAM SOCK_STREAM
连接 无握手 必须先 connect() / accept()
地址附加在哪 每个分组都要附目的 IP + 端口 只在建连时指定一次
客户端调用 sendto() / recvfrom() connect() / send() / recv()
服务器端调用 bind() / recvfrom() / sendto() bind() / listen() / accept() / recv() / send()
接收方能否知道发送方 能(recvfrom() 返回地址) 建连时就知道了
服务器套接字数量 1 个 1 个欢迎 + 每客户 1 个连接
可靠性 可能丢失或乱序 可靠、按序的字节流("管道")

三个最容易考的差异:

  1. UDP 客户没有 connect(),TCP 客户有
  2. UDP 服务器没有 listen() / accept()
  3. TCP 的 recv() 只读字节,不像 UDP 的 recvfrom() 还返回地址

第三部分:P2P

十五、纯 P2P 架构

特性 说明
无 always-on 服务器 没有中心节点
任意端系统直接通信 对等方之间直连
对等方间歇连接且会换 IP 这是管理上的主要难点

讲义给的三类例子:

类别 代表
文件分发 BitTorrent
流媒体 Zattoo、KanKan
VoIP Skype

十六、文件分发时间:C/S vs P2P(最可能出计算题)

问题:把大小为 的文件从一台服务器分发给 个对等方需要多久? 对等方的上传/下载能力是受限资源。

符号约定

符号 含义
文件大小
服务器上传能力
对等方 的上传能力
对等方 的下载能力
最小的客户下载速率

客户-服务器

两项各自的来源:

项 推导
服务器必须「顺序地」发送 N 份文件副本
发一份要 → 发 N 份要 —— 随 N 线性增长
每个客户都要下载一份完整文件
最慢的那个客户(最坏情况)要

P2P

三项各自的来源:

项 推导
⚠️ 服务器至少要上传一份副本(注意:不是 N 份!)—— 剩下的靠对等方之间互传
每个客户都要下载一份
所有客户总共必须下载 比特 = 系统总共必须上传 比特
最大总上传速率 =

⚠️ 第一项是最常错的:很多人写成 ,那是 C/S 的式子。 P2P 的关键就在于「服务器只需上传一份,剩下的让对等方帮忙散播」。

十七、为什么 P2P 能扩展(核心洞见)

讲义 p29 的原话: 「分子随 N 线性增长……但分母也随之增长,因为每个新对等方都带来了服务能力。」

看第三项的结构:

分子分母同时含

取极限:

这就是水平渐近线 —— 无论多少个对等方,分发时间不会超过 (即「单个对等方上传完一份文件所需的时间」)。 而 C/S 的 是没有上界的直线。

用讲义 p30 的参数验证( 小时, , )

(小时) (小时) C/S 是 P2P 的几倍
1 0.10 0.10 1.0×
10 1.00 0.50 2.0×
20 2.00 0.67 3.0×
35 3.50 0.78 4.5×
∞ → 1.00 ∞

两条曲线的形状(讲义 p30 的图):

  • C/S 是直线上升,无上界
  • P2P 趋于水平渐近线 小时

考试若问「N 很大时 P2P 分发时间趋于多少」,答案就是 。

十八、BitTorrent

背景数字(讲义 p31)

项 值
2012 年占欧洲互联网流量 20%
典型用途 Linux 发行版、软件补丁、影片分发
目标 快速地把大文件复制给大量客户

核心组件

概念 说明
torrent 交换某文件分块的一组对等方
tracker 追踪参与该 torrent 的对等方(下载者/拥有者)
.torrent 文件 由 Web 服务器托管,含文件长度、哈希、tracker 的 URL
chunk(分块) 256 KB(讲义 p31 也写 256 kB–1 MB)

一个对等方的生命周期

阶段 发生了什么
加入 向 tracker 注册,获得对等方列表,连接其中一个子集("邻居")
初始状态 没有任何分块,随时间从其他对等方积累
下载中 同时也在向别人上传分块
动态调整 可能更换交换分块的伙伴
churn(搅动) 对等方随时来去
完成后 可以(自私地)离开,也可以(利他地)留在 torrent 里当种子

两个核心策略(必考)

策略一:请求分块 —— rarest first(最稀缺优先)

步骤 动作
1 周期性地问每个对等方「你有哪些分块」
2 从对等方请求缺失的分块,最稀缺的优先

为什么要最稀缺优先:如果人人都先要最常见的分块,稀缺分块的持有者一旦离开, 整个 torrent 就再也拼不出完整文件了。 优先复制稀缺分块能最大化文件在群体中的可用性。

策略二:发送分块 —— tit-for-tat(一报还一报)

规则 数值 / 说明
向谁发送 当前以最高速率给她发分块的 4 个对等方(top 4)
其他对等方 被「阻塞(choked)」—— 收不到她的分块
重估周期 每 10 秒重估 top 4
乐观疏通 每 30 秒随机选另一个对等方开始发送分块(optimistically unchoke)
结果 被乐观疏通的新对等方可能进入 top 4

tit-for-tat 的正反馈循环(讲义 p35)

(1) Alice 乐观疏通 Bob
↓
(2) Alice 成为 Bob 的 top-4 之一,Bob 回报(给 Alice 发分块)
↓
(3) Bob 成为 Alice 的 top-4 之一
↓
双方都拿到更快的下载速度

讲义的结论:上传速率越高 → 找到越好的交易伙伴 → 拿到文件越快。

为什么需要「乐观疏通」这个随机机制: 如果只按 top-4 规则,新加入的对等方(还没有任何分块可上传)永远进不了任何人的 top 4, 就会饿死。 每 30 秒的随机疏通给了他们「起步资金」。

十九、分布式哈希表(DHT)

是什么

DHT 是一个分布式的 P2P 数据库,存储 (key, value) 对。

能力 说明
分布存储 把键值对分散到许多对等方上
查询 对等方用 key 查询 DHT,DHT 返回匹配的 value
插入 对等方也能插入 (key, value) 对

讲义的例子:key = 社保号,value = 人名。

DHT 要解决的两个问题

  1. Assign the keys —— 键值对该放在哪个对等方上?
  2. Lookup the keys —— 给定 key,怎么找到持有它的主机?

二十、把 key 分配给哪个对等方

基本思路(讲义 p39)

步骤 动作
1 key 生成一个整数
2 给每个对等方也分配一个整数 ID
3 把 (key, value) 放在「ID 最接近 key」的对等方上

具体做法(讲义 p40)

要素 说明
对等方 ID 范围 ,用 位表示
key 范围 同一个范围
怎么把原始 key 变成整数 用哈希函数

哈希函数的定义(讲义原文):把任意大小的数据映射到固定大小数据的函数。 例子:15 = hash("Led Zeppelin IV")

这就是它叫「哈希」表的原因(distributed "hash" table)。

规则:分配给「最接近的 ID」,这里定义为立即后继(immediate successor)

讲义 p41 的例子( ,对等方 1, 3, 4, 5, 8, 10, 12, 14):

key 后继对等方 说明
0 1 大于等于 0 的最小 ID
1 1 恰好命中某个节点
2 3 —
13 14 讲义给的例子
14 14 恰好命中
15 1 ⚠️ 没有 ≥15 的对等方 ⇒ 环回到最小的 1
16 1 同样环回

⚠️ 「环回」是最常考的边界情况 —— key 超过最大对等方 ID 时,绕回环的起点。

另一个陷阱:「最接近」在这里定义为「立即后继」,不是「数值上最近」。 例如 key = 13 时,节点 12 在数值上更近(差 1),但答案是 14(后继)。

二十一、环形 DHT 与查询代价

基础版:只知道立即后继(讲义 p43–44)

结构:每个对等方只知道自己的立即后继,形成一个环。

讲义 p44 的例子:对等方 0001, 0011, 0100, 0101, 1000, 1010, 1100, 1111

问题 答案
谁负责 key 1110? 节点 1111
为什么 ,最小的 ≥14 的节点 ID 是
代价 讲义标注沿环传了 6 条消息

💡 关于「6 条」的计数口径:沿后继从 0001 走到 1111 要经过 7 个节点间隔, 讲义图上标了 6 个查询消息 —— 差异在于是否计入最后的「I am」应答,或查询从哪个节点发起。 考试记结论即可:基础环形 DHT 平均需要 条消息。

改进版:加捷径(讲义 p45–46)

每个对等方记录三样东西:

记录 作用
successor(后继) 环上的下一个
predecessor(前驱) 环上的上一个
shortcuts(捷径) 跳到远处的节点,加速请求转发

效果:同一个查询从 6 条消息降到 2 条(讲义 p46)。

可设计成个邻居、条消息

两种版本的复杂度对比

节点数 平均跳数 跳数
8 4 3
64 32 6
1,024 512 10
1,000,000 500,000 ≈ 20

这张表说明了为什么必须加捷径:百万节点时, 要跑 50 万跳, 只要 20 跳。

Chord

Chord 是 DHT 的一个具体实例 —— 论文标题: "Chord: A scalable peer-to-peer lookup service for internet applications"

一个 Chord 节点有:后继、前驱、若干捷径。

二十二、处理对等方搅动(Peer Churn)

机制 说明
每个对等方知道它「两个」后继的地址 ⚠️ 不是一个!
周期性 ping 这两个后继 检查存活
若立即后继离开 把下一个后继升为新的立即后继

讲义 p47 的例子(环:1, 3, 4, 5, 8, 10, 12, 15;对等方 5 突然离开):

步骤 动作
1 对等方 4 检测到 5 已离开
2 把 8 设为自己的立即后继
3 问 8「你的立即后继是谁」
4 把 8 的立即后继(10)设为自己的第二后继

「为什么要知道两个后继而不是一个?」是标准 MCQ: 因为立即后继挂掉时需要立刻有备用,否则环就断了,查询无法继续转发。

💡 讲义还留了个问题:「如果对等方 13 想加入怎么办?」 答案思路:13 的后继应该是 15,前驱应该是 12 —— 需要通知 12 把后继改成 13, 并把原属于 13 范围的 key 从 15 迁移过来。


第四部分:配套 Tutorial —— HTTP Wireshark

⚠️ COMP5416 的 tutorial 比 lecture 慢一周 —— Week 4 模块里的这份 tutorial 练的是 Week 03 的 HTTP。

二十三、Wireshark 的分层视图

HTTP 消息装在 TCP 段里,TCP 段装在 IP 数据报里,IP 数据报装在以太网帧里 —— Wireshark 会同时显示 Frame / Ethernet / IP / TCP / HTTP 五层信息。

操作建议(tutorial 原文):把 Frame、Ethernet、IP、TCP 的三角形收起来(右指), 只展开 HTTP 那一行 —— 减少非 HTTP 信息的干扰。

💡 tutorial 特别提醒:忽略 favicon.ico 的 GET 和响应 —— 那是浏览器自动去问 「有没有小图标显示在地址栏旁边」,与实验无关。

二十四、Exercise 1:基本 GET/响应

问题 答案
浏览器/服务器跑的 HTTP 版本 两端都是 HTTP/1.1;浏览器声明 Accept-Language: en-US
本机与 gaia.cs.umass.edu 的 IP 地址 直接读抓包窗口的 Source / Destination 列即可(示例中是 10.61.0.119 → 128.119.245.12)
抓到几条 HTTP 消息 2 条:浏览器的 GET + 服务器的响应
服务器返回的状态码 200
HTML 文件上次修改时间 不到一分钟前
返回的内容字节数 128 字节(等于 "Line-based txt data" 的长度)
原始数据里有未显示的首部吗 没有,所有首部都列出来了

「为什么是不到一分钟前」(tutorial 专门解释了): gaia.cs.umass.edu 服务器每分钟把该文件的 last-modified 时间设为当前时间。 所以隔一分钟再访问,文件就显得「刚被修改过」,浏览器会重新下载「新」副本 —— 这个设计正是为了让下一个练习(条件 GET)能观察到两种不同的结果。

二十五、Exercise 2:条件 GET(直接对应 Week 3 的考点)

前提:先清空浏览器缓存(tutorial 要求)。

步骤 观察结果
第一次 GET 没有 IF-MODIFIED-SINCE 行
服务器第一次响应 显式返回了文件内容
第二次 GET 出现 IF-MODIFIED-SINCE: 行
服务器第二次响应 HTTP/1.1 304 Not Modified,未返回内容 —— 浏览器从自己的缓存加载

这正是 Week 03 讲义条件 GET 那一节的实测版本。 做题时能把「第一次无 If-modified-since、第二次有且返回 304」讲清楚就满分。

二十六、Exercise 3:HTTP 认证(重要安全结论)

目标 URL:http://gaia.cs.umass.edu/wireshark-labs/protected_pages/HTTP-wireshark-file5.html 用户名:wireshark-students 密码:network

步骤 结果
初次 GET 的服务器响应 401 Authorization required
第二次 GET 新增的字段 Authorization: Basic 后跟一串编码字符

实际抓到的串:

d2lyZXNoYXJrLXN0dWRlbnRzOm5ldHdvcms=

Base64 解码后:

这个 tutorial 最重要的结论(讲义原文的图题就叫 "Password appears in clear text"): 看起来像加密,其实只是 Base64 编码 —— 用户名和密码是明文可恢复的。

格式规律:Basic 认证的编码内容永远是 用户名:密码,中间用冒号分隔。

这直接呼应 Week 03 的两个点: 「TCP/UDP 不加密,明文密码穿越互联网」 和 「需要 SSL」。

⚠️ MCQ 陷阱:Base64 是编码(encoding)不是加密(encryption)。


第五部分:MCQ 速查表

DNS

项 答案
DNS 端口 53
传输协议 主要 UDP(大响应/区域传送用 TCP)
根服务器数量 13 个(逻辑上)
本地 DNS 服务器 不严格属于层级结构;又叫「默认名字服务器」;充当代理
四种 RR A(主机名→IP)、NS(域→权威服务器名)、CNAME(别名→规范名)、MX(→邮件服务器)
RR 格式 (name, value, type, ttl)
迭代 vs 递归 迭代:告诉你下一个问谁;递归:替你把答案取回来
两种查询的消息数 本例都是 8 条,差别在「谁承担往返」
缓存性质 TTL 到期消失;可能过时 ⇒ 「尽力而为」
不集中式的三个理由 单点故障、距离远、可扩展性
NS 记录的伴生记录 必须配一条 A 记录(胶水记录)

套接字

项 答案
UDP socket 类型 SOCK_DGRAM
TCP socket 类型 SOCK_STREAM
TCP 服务器区分多个客户靠什么 源端口号
谁控制传输层 操作系统(应用层才由开发者控制)
UDP 服务器有 listen/accept 吗 没有
TCP 服务器有几个套接字 1 个欢迎 + 每客户 1 个连接
哪个调用返回发送方地址 recvfrom()(UDP 独有)

P2P

项 公式 / 答案
C/S 分发时间
P2P 分发时间
P2P 第一项 ⚠️ 不是
P2P 的 N→∞ 极限 (趋于水平渐近线)
BitTorrent 分块 256 KB
请求策略 rarest first
发送策略 tit-for-tat,top 4,每 10 秒重估
乐观疏通 每 30 秒随机选一个
乐观疏通的作用 让没有分块的新对等方不至于饿死

DHT

项 答案
key 分配规则 给「立即后继」;超出最大 ID 则环回
「最接近」的定义 后继,不是数值最近
基础环形 DHT 查询代价
加捷径后 个邻居、 条消息
Chord 节点记录什么 后继、前驱、捷径
每个对等方记几个后继 两个(应对 churn)
为什么要两个 立即后继挂掉时环不至于断

最容易错的 6 个点

  1. P2P 公式第一项是 ,不是
  2. DHT 用「后继」不是「数值最近」;超过最大 ID 要环回
  3. BitTorrent:10 秒是重估 top 4,30 秒才是乐观疏通
  4. 本地 DNS 服务器不属于 DNS 层级结构
  5. NS 记录必须配 A 记录,否则拿到名字也联系不上
  6. Base64 是编码不是加密 —— Wireshark tutorial 的核心结论

第六部分:本讲在考纲中的位置

Week 主题 笔记
1 Introduction Week 01
2 Performance Week 02
3 Applications Week 03
4 DNS and P2P 本文
5 Transport Week 05
6 TCP ⚠️ Canvas 未发布

tutorial 与 lecture 的一周错位:

Tutorial 所在周 练的内容
Week 2(T1 博弈论) Week 1 导论
Week 3(Lab 2 Performance) Week 2 性能
Week 4(HTTP Wireshark) Week 3 的 HTTP —— 见本文第四部分
Week 5(DNS) 本讲的 DNS —— 见 Week 05 笔记第八部分

所以本讲 DNS 部分的配套练习在 Week 5 的 tutorial 里。

配套练习:20 题期中模拟卷 的板块三(Q12–Q16)专测本讲内容。