COMP5416 Kurose 交互题库题解:第三章传输层 全部 9 题(期末范围)
COMP5416 Kurose 交互题库题解:第三章传输层(全部 9 题)
课程:COMP5416/COMP4416 — Advanced Network Technologies,Semester 2 2026 来源:Kurose 官方交互练习站 第三章 9 道题 ⚠️ 范围提醒:根据 Ed Discussion #22,Transport 层(Week 5)不在期中考试范围内,期中真实范围是 Week 1–4(对应 考纲对照指南 里的"超纲"清单)。这一章的内容属于期末考试范围,现在整理出来是为了给期末复习打提前量,不是期中必做。 上一篇:第二章应用层 8 题(Week 3–4,期中范围)
🎲 关于随机数字,务必先读这段:这个站上很多题目(尤其是本章的 Checksum、TCP 序号/ACK、TCP RTT、TCP 重传、Mux/Demux 端口号)每次刷新页面/点"Another Problem Like This"都会重新生成一套新的随机数字,有些题目(如 rdt3.0 缺失的 transition、TCP 拥塞窗口演化图)连"事件发生在哪个时刻"都会变。下面记录的只是我这次抓取时生成的那一个实例——重点请放在每一题的解法、公式和判断逻辑上,不要死记这一组具体数字。你自己打开网站做题时,把这里的方法套到你看到的那组新数字上就行。所有数值我都已经用 Python 代码独立验算过,和官网 Show Solution 一致。
目录
| # | 题目 | 小问数 | 考点 |
|---|---|---|---|
| 1 | Computing an Internet Checksum | 2 | 一补数求和、校验和 |
| 2 | Reliable Data Transfer - rdt2.2 | 13 | rdt2.2 状态机、序号/ACK |
| 3 | Reliable Data Transfer - rdt3.0 | 1 | rdt3.0 状态机、超时重传 |
| 4 | TCP Sequence and ACK Numbers with Segment Loss | 2 | TCP 序号累加、累积确认 |
| 5 | Computing TCP's RTT and Timeout Values | 9 | EstimatedRTT / DevRTT / 超时计算 |
| 6 | TCP in Action - Slow Start, Congestion Avoidance, and Fast Retransmit | 6 | 拥塞窗口演化、ssthresh |
| 7 | TCP Retransmissions | 15 | 滑动窗口、累积确认、重复 ACK |
| 8 | UDP Multiplexing and Demultiplexing | 8 | UDP 二元组分解 |
| 9 | TCP Multiplexing and Demultiplexing | 8 | TCP 四元组分解 |
一、Computing an Internet Checksum
题目设定
两个 16 位字(二进制):
11110011 01111101 (十进制 62333) |
Internet 校验和的算法:把若干个 16 位字做一补数加法(普通二进制加法,若产生第 17 位的进位,就把这个进位加回结果的最低位),最后把加和结果按位取反(一补),就是校验和。
Q1:这两个 16 位数的和是多少?
按二进制逐位相加:
11110011 01111101 |
Q2:用 Q1 的和,计算校验和
校验和 = 上面这个和的按位取反(一补数):
考点重点:一补数加法的核心是"进位不能丢,要回卷加到最低位"——这和普通二进制加法唯一的区别就在这里;忘了这一步是这道题最容易丢分的地方。校验和本身就是"和"的按位取反,接收端只要把收到的数据 + 校验和再做一次一补数加法,结果应该全 1(否则判定出错)。
二、Reliable Data Transfer - rdt2.2
题目设定
rdt2.2 协议(教材 Figure 3.13 发送方 FSM / Figure 3.14 接收方 FSM):信道只会讹误(corrupt)不会丢包或乱序。下面是发送方与接收方之间交换 4 个数据分组和 3 个 ACK 的时序(本例抓到的这一次实例里,前 4 次半程传输——即 t=0 到 t=3——全部成功,没有发生讹误):
上面是我按本例的 4 段成功交换重新画的示意图(原题配图见 rdt2.2 官方页面,官方图里后面还画了一次讹误+超时重传,但本例的 13 道小问只问到 t=3 这一段,讹误部分不影响这 13 个答案)。
解题逻辑
核心是死记 rdt2.2 的两张 FSM 图(教材 Fig 3.13/3.14),本质就是"乒乓球":发送方发一个包就切到"等 ACK"状态,收到匹配的 ACK 才切到"等上层调用"状态然后立刻发下一个包;接收方同理,收到匹配序号的包就交付+发 ACK,切到"等下一个序号"状态。
| 时刻 | 事件 | 发送方状态 | 接收方状态 | 序号/ACK |
|---|---|---|---|---|
| t=0 | 发送方发 data,seq=0 | Wait for ACK 0(刚发完) | Wait for 0 from below(还没收到) | seq = 0 |
| t=1 | 数据到达接收方;接收方发 ACK 0 | Wait for ACK 0(还没收到 ACK) | Wait for 1 from below(已交付 seq0) | ACK = 0 |
| t=2 | ACK 0 到达发送方;发送方立即发 seq=1 | Wait for ACK 1(已发下一包) | Wait for 1 from below(还没收到 seq1) | seq = 1 |
| t=3 | 数据到达接收方;接收方发 ACK 1 | Wait for ACK 1(还没收到 ACK) | Wait for 0 from below(已交付 seq1) | ACK = 1 |
逐题答案
Q13:接收方把收到分组的数据交付给上层几次?
考点重点:这类题不用死记具体状态名,只要记住 rdt2.2 是"0/1 交替 + 乒乓确认":发送方永远在"等对应 0/1 的 ACK"和"等上层新数据"之间交替;接收方永远在"等对应 0/1 的新分组"之间交替,收到就交付+发对应 ACK,没收到(讹误/重复)就丢弃+重发上一次的 ACK。把时间轴上"谁发了什么、状态往哪边切"画成表格,逐格填就不会错。
三、Reliable Data Transfer - rdt3.0
题目设定
rdt3.0 协议在 rdt2.2 基础上加了超时重传(应对丢包),FSM 里每条转移都标了编号:发送方转移记作 S0–S9,接收方转移记作 R0–R3。
上面是我按官方 FSM(教材 Figure 3.15)重新整理的转移条件表(原图见 rdt3.0 官方页面),编号和条件与官网一致,方便对照着推。
给定的转移序列(一个环节被替换成了 *):
Q1:缺失的 transition 是什么?
逐步还原:
- S0:发送方发出 seq0,启动计时器,进入"等 ACK0"。
*(缺失的一步):紧接着,必须是接收方对这个刚到达的 seq0 分组做出的反应。因为下一步是 S1(发送方在"等ACK0"状态收到讹误/错误 ACK,原地忽略),说明接收方这次没有正常返回 ACK0,而是返回了一个讹误的包,或者……更准确地说:seq0 这个分组本身在传输途中被讹误,接收方在"等 0"状态收到讹误分组,按 FSM 只能重发上一次的 ACK(还没交付过任何东西时,FSM 代码仍会按"重发 ACK1"的通用逻辑执行)——这正是接收方 FSM 里 R3("等0"状态下收到讹误或重复分组 → 自环,重发 ACK)的定义。- S1:发送方收到这个(内容错误的)ACK,判定为讹误或者不是期望的 ACK0 → 自环忽略,继续等待。
- S2:迟迟等不到正确 ACK0,计时器超时 → 重发 seq0。
- R0:这一次 seq0 正确到达 → 接收方交付、发 ACK0、切到"等1"。
- S3:发送方收到正确 ACK0 → 停计时器,切到"等上层调用1"。
- S5:上层调用发送,发出 seq1。
- R2:seq1 正确到达 → 接收方交付、发 ACK1、切到"等0"。
- S8:发送方收到正确 ACK1 → 停计时器,切到"等上层调用0",一轮结束。
考点重点:这类"补全 transition 序列"的题,方法永远是同一个:把每个已知编号对应的"触发条件 + 动作 + 状态跳转"写出来,前后状态必须能对得上(上一条的"跳转到"状态 = 下一条的"发生在哪个状态")。缺失的那一环,看它前后相邻的两条分别是"发生在什么状态",反推中间必须发生什么事件才能把两边接起来——S0 结束在"等ACK0",S1 也发生在"等ACK0",说明中间这一步没有改变发送方的状态,那就只能是接收方那一侧发生的事情(R0–R3 之一),再看 S1 的触发条件是"收到讹误/错误ACK",倒推出接收方一定是收到了讹误分组并重发了上一次的 ACK,也就是 R3。
四、TCP Sequence and ACK Numbers with Segment Loss
题目设定
TCP 发送方向接收方发送数据,发送方→接收方方向可能丢分组。发送方初始窗口为 4 个分组,起始序号 272,前 4 个分组每个 439 字节。发送方与接收方之间单程时延 7 个时间单位,所以第 1 个分组在 t=8 到达接收方。本例中,4 个分组里有 1 个在中途丢失。
4 个分组按序发出(本例第 4 个在中途丢失,未到达接收方)。原题配图见 官方页面。
解题逻辑
TCP 序号 = 数据流中第一个字节的编号,不是"第几个分组",所以下一个分组的序号 = 上一个分组的序号 + 上一个分组携带的字节数(而不是简单 +1)。ACK 号 = 接收方期望收到的下一个字节的序号(累积确认),如果某个分组没有正常到达,接收方就不会为它生成新的 ACK。
Q1:4 个分组各自的序号
Q2:接收方对每个分组回复的 ACK 号
前 3 个分组(对应第 1、2、3 段)都正常到达,接收方分别 ACK
下一个期望字节:收到 seg1(到 seq710 为止)后 ACK 711;收到 seg2 后 ACK
1150;收到 seg3 后 ACK 1589。第 4
个分组丢失,接收方从未收到它,自然也不会为它产生 ACK,记为
x。
考点重点:这类题的两个易错点——① 序号是按字节累加,不是按分组数累加(
,不是 );② ACK 号永远是"接收方下一个期望收到的字节",只要某个分组没到,接收方就没有理由更新 ACK(这里没有乱序重传的复杂情况,简单地"丢了就没有对应 ACK")。
五、Computing TCP's RTT and Timeout Values
题目设定
当前 TCP 的 estimatedRTT = 400 ms,DevRTT =
48 ms。接下来测得 3 个新的 SampleRTT:270
ms、400 ms、350 ms。取
⚠️ 顺序陷阱:公式里 DevRTT 用到的
里的 EstimatedRTT,是更新前(上一轮)的旧值,一定要先算 DevRTT,再更新 EstimatedRTT,顺序反了两个值都会错。
第一次测量(SampleRTT = 270)
第二次测量(SampleRTT = 400)
第三次测量(SampleRTT = 350)
汇总表(已用 Python 逐位验算)
| 轮次 | SampleRTT | EstimatedRTT | DevRTT | Timeout |
|---|---|---|---|---|
| 1 | 270 | 383.75 | 68.50 | 657.75 |
| 2 | 400 | 385.78 | 55.44 | 607.53 |
| 3 | 350 | 381.31 | 50.52 | 583.40 |
考点重点:三个公式必须按 DevRTT → EstimatedRTT → Timeout 的顺序算,且 DevRTT 公式里那个"旧的 EstimatedRTT"千万别提前更新。
、 是教材给的推荐默认值,题目不特别说明时直接套用;Timeout 恒等于 EstimatedRTT 加 4 倍 DevRTT,这个"4 倍"系数是死记硬背的部分,务必记牢。
六、TCP in Action - Slow Start, Congestion Avoidance, and Fast Retransmit
题目设定
教材 Figure 3.53 的抽象模型:TCP 在每个时间单位(= 1 RTT)开始时,发送 cwnd 个分组组成的一"飞行批次(flight)";这批分组的结局只有三种——全部被 ACK(cwnd 按当前阶段规则增长)、首个分组超时(timeout),或首个分组收到三次重复 ACK(triple duplicate ACK)。本题给出 cwnd 随时间演化的曲线,要求反推每个时刻 TCP 处于哪个阶段。初始 cwnd = 1,初始 ssthresh = 8。
这张图是我按官网这一实例给出的 cwnd 曲线(TCP Evolution 官方页面)用代码重新算出全部 40 个点后自己重绘的,不是原站截图;绿点=慢启动,黄点=拥塞避免,橙点=快速恢复,标注了三次 timeout 和一次三次重复 ACK 的发生位置。
解题方法:三条铁律 + 一个易错点
- 慢启动(Slow Start):cwnd 从 1
开始,每经过一个成功的 RTT就翻倍(
),直到 cwnd 达到或超过 ssthresh 为止。 - 拥塞避免(Congestion Avoidance):一旦 cwnd ≥ ssthresh,改为每个成功 RTT 只 +1(线性增长,"加性增大")。
- 丢包后的反应("乘性减小"):
- 超时(timeout):说明网络拥塞严重,ssthresh ← cwnd/2(向下取整),cwnd 重置为 1,重新进入慢启动——曲线上表现为"断崖式跌回 1"。
- 三次重复 ACK(fast retransmit):说明只是个别分组丢失、网络还没那么糟,ssthresh ← cwnd/2,cwnd ← ssthresh + 3,直接进入快速恢复(cwnd 不用跌回 1);等收到新的 ACK 后,cwnd 回落到新 ssthresh,从这个值继续做拥塞避免的线性增长。
- ⚠️ 最容易忽略的一点:ssthresh
只有"取值真的变了"才算"变化"——如果
算出来的新值刚好和旧值相同,就不算一次"ssthresh 改变"事件(比如本例 t=12 发生超时时 cwnd=16, ,正好等于当时的 ssthresh(8),所以 t=13 时不计入"ssthresh 变化时刻",即便底层确实重新赋值了一次)。
按本例逐段还原
| 时间段 | cwnd 序列 | 阶段 | 触发的下一事件 |
|---|---|---|---|
| t=1–3 | 1, 2, 4 | 慢启动 | t=3 末 cwnd(4)→8=ssthresh,t=4 起转拥塞避免 |
| t=4–12 | 8,9,10,...,16 | 拥塞避免 | t=12 超时:新 ssthresh=⌊16/2⌋=8(和旧值相同,不算"变化"),cwnd→1 |
| t=13–15 | 1, 2, 4 | 慢启动 | t=15 末 cwnd(4)→8=ssthresh,t=16 起转拥塞避免 |
| t=16–18 | 8, 9, 10 | 拥塞避免 | t=18 超时:新 ssthresh=⌊10/2⌋=5(比旧值 8 小,t=19 记一次"ssthresh 变化"),cwnd→1 |
| t=19–21 | 1, 2, 4 | 慢启动 | t=21 超时(cwnd=4 还没达到新 ssthresh(5),仍在慢启动阶段就中招):新 ssthresh=⌊4/2⌋=2(t=22 记一次变化),cwnd→1 |
| t=22 | 1 | 慢启动 | cwnd(1)<ssthresh(2),下一步翻倍到 2=ssthresh,t=23 起转拥塞避免 |
| t=23–28 | 2,3,4,5,6,7 | 拥塞避免 | t=28 三次重复 ACK:新 ssthresh=⌊7/2⌋=3(t=29 记一次变化),cwnd←3+3=6,进入快速恢复 |
| t=29 | 6 | 快速恢复 | 收到新 ACK,cwnd 回落到 ssthresh=3,t=30 起恢复拥塞避免 |
| t=30–40 | 3,4,5,...,13 | 拥塞避免 | (曲线到 t=40 为止,未再丢包) |
逐题答案
Q1:慢启动的时刻
Q2:拥塞避免的时刻
Q3:快速恢复的时刻
Q4:因超时丢包的时刻
Q5:因三次重复 ACK 丢包的时刻
Q6:ssthresh 发生变化的时刻
考点重点:这题的本质是状态机模拟,不是死记一张图。做题四步走:① 先按"慢启动翻倍/拥塞避免+1"把曲线分段(找出每一段斜率变化的拐点);② 每次"断崖下跌"就是一次事件——跌到 1 是超时,没跌到 1、跌到一个中间值就继续涨是三次重复 ACK+快速恢复;③ 用跌之前的 cwnd 算出
作为新 ssthresh,和旧 ssthresh 比较,只有真的变了才算一次"变化";④ 快速恢复只占触发的那一个时间单位,下一个单位就已经回落到新 ssthresh、正式回到拥塞避免了。
七、TCP Retransmissions
题目设定
TCP 发送方要发送共 10 个分组,初始窗口为 5,在 t=1,2,3,4,5 各发一个。起始序号 36,每个分组 725 字节。单程时延 7 个时间单位,第 1 个分组 t=8 到达接收方,对应 ACK 在 t=15 到达发送方。本例中,5 个分组里有 2 个中途丢失,但所有 ACK 都不会丢;没有超时,接收方丢弃所有失序到达的分组(不缓存乱序包)。
解题逻辑
第一步照样是算 5 个初始分组的序号(序号按字节累加):
第二步看 ACK:接收方只对"顺序正确"的分组回复新的累积 ACK,前两个正常到达就正常确认;本例里第 3、4 个分组(对应 t=10、11 应该收到的那两个)丢失,所以接收方收不到它们,没有 ACK 可发;第 5 个分组虽然正常到达,但因为前面第 3 个空了一个缺口,接收方仍在等第 3 个分组,只能对第 5 个分组回复重复 ACK(值仍是"下一个期望字节",也就是第 3 个分组的序号)。
第三步看窗口滑动:只有当 ACK 真正把已发送但未确认的最早字节确认掉,窗口才会右移、腾出新的发送额度。t=15 到达的 ACK 对应第 1 个分组 → 窗口右移 1 格,允许发送第 6 个新分组;t=16 到达的 ACK 对应第 2 个分组 → 窗口再右移 1 格,允许发送第 7 个新分组。但第 3、4 个分组的 ACK 永远不会来(因为分组本身丢了,没有触发重传机制——题目明确"没有超时"),所以窗口卡死在这里不再前进,t=17、18、19 时发送方没有新数据可发。
逐题答案
Q1–Q5:t=1 到 t=5 发送的 5 个分组的序号
Q6–Q10:t=8 到 t=12 接收方回复的 ACK
| 时刻 | 对应哪个分组 | ACK |
|---|---|---|
| t=8 | 第 1 个分组正常到达 | 761(下一个期望字节) |
| t=9 | 第 2 个分组正常到达 | 1486 |
| t=10 | 第 3 个分组丢失,无 ACK | x |
| t=11 | 第 4 个分组丢失,无 ACK | x |
| t=12 | 第 5 个分组到达,但仍在等第 3 个 → 重复 ACK | 1486 |
Q11–Q15:t=15 到 t=19,发送方发出的新分组序号
| 时刻 | 触发的 ACK | 窗口能否前移 | 新发送的序号 |
|---|---|---|---|
| t=15 | ACK(761) 到达(确认第 1 个) | 可以,+1 格 | 3661( |
| t=16 | ACK(1486) 到达(确认第 2 个) | 可以,+1 格 | 4386( |
| t=17 | 只有更早的重复 ACK(1486),第 3、4 个的 ACK 从未到达 | 不能 | x |
| t=18 | 同上,窗口卡住 | 不能 | x |
| t=19 | 同上 | 不能 | x |
考点重点:这题综合了三件事——① 序号按字节累加;② 累积确认(cumulative ACK):ACK 值永远是"最早还没收到的那个字节",中间有缺口时,后面即使收到了新数据,回复的 ACK 也不会往前走(这就是"重复 ACK"的来源,触发快速重传的机制正是数出现 3 个重复 ACK,但本题明确说"没有超时"也没让你判断快速重传,只是单纯考"窗口没滑动就没有新数据可发");③ 发送窗口只有被"确认掉最早未确认字节"才会滑动——这也是为什么第 3、4 个分组丢失后,尽管第 5 个已经到了接收方,发送方却再也发不出新东西:窗口卡在第一个"漏洞"上,动不了。
八、UDP Multiplexing and Demultiplexing
题目设定
左、右两个客户端都用 UDP 和同一个服务器通信,服务器用同一个 socket 同时服务两个客户端(UDP 的 demux 只看目的端口,不看四元组,所以一个 socket 可以收所有发到这个端口的包,不管来自谁)。
按官方端口号重绘的示意图(原图见 UDP Mux/Demux 官方页面)。左客户端进程 P3 绑定端口 6678,右客户端进程 P4 绑定端口 5858,服务器进程 P1 用同一个 socket 绑定端口 6384。
逐题答案
UDP 的每个分组只由(源端口、目的端口)决定往哪个方向走,四个分组分别是:A(左客户端→服务器)、B(服务器→左客户端)、C(右客户端→服务器)、D(服务器→右客户端)。
考点重点:UDP 的分解(demultiplexing)只看目的端口——只要是发到 6384 端口的包,不管来自 6678 还是 5858,服务器上同一个 socket 都收得到,应用层要靠分组里的源 IP+源端口自己去区分是哪个客户端发来的。这也是这道题设计的关键:服务器只用了一个 socket 就同时服务了两个客户端,这在 TCP 里是不可能的(对比下一题)。
九、TCP Multiplexing and Demultiplexing
题目设定
左、右两个 TCP 客户端与服务器通信。服务器用一个欢迎 socket(welcoming socket,图中不显示)监听端口 7395,每接受一个连接请求就创建一个新的已连接 socket——本例中一共接受了 3 个连接:左客户端 1 个(P1,端口 7096),右客户端 2 个(用了两个不同的本地 socket:P2 端口 5511,P3 端口 5768)。
按官方端口号重绘的示意图(原图见 TCP Mux/Demux 官方页面)。本例只展示了 A(左客户端上行)、B(服务器回左客户端)、C(右客户端 socket2 上行)、D(右客户端 socket1 上行)这 4 个分组。
逐题答案
考点重点:这是全课程区分 UDP vs TCP 分解方式最经典的对比题——TCP 的分解用完整四元组(源IP、源端口、目的IP、目的端口),所以哪怕左右两个客户端上的分组目的端口都是同一个 7395(欢迎端口衍生出的已连接 socket 本地端口不变),服务器依然能靠源 IP+源端口不同把它们分流到三个不同的已连接 socket(P4/P5/P6)上,这一点和上一题 UDP 只看目的端口就能共用一个 socket 形成鲜明对比。做题时先认出"谁是欢迎 socket 的端口"(本例 7395,所有连接的本地端口都不变),再看每个分组的源端口来判断它属于哪一条连接。
考点重点(第三章全览)
- 一补数校验和:普通二进制加法,若产生第 17 位进位要回卷加到最低位,最后按位取反得到校验和;接收端验证时把数据+校验和再加一次,结果应全 1。
- rdt2.2:发送方在"等 ACK 0/1"与"等上层调用"之间交替;接收方在"等 seq 0/1"之间交替,收到匹配序号才交付+发对应 ACK,收到讹误/不匹配就原地重发上一次的 ACK(不是发新 ACK,也不改变状态)。
- rdt3.0:在 rdt2.2 基础上加了计时器——等 ACK 期间超时就重发;补全"缺失 transition"题的方法是前后状态必须能接上,倒推中间发生了什么事件。
- TCP 序号按字节流累加(
,不是 ),ACK 是累积确认("下一个期望字节"),分组丢了就没有对应 ACK;乱序到达但前面有缺口时,只能重复确认上一次的 ACK。 - TCP RTT/超时三兄弟公式:先算 DevRTT(用旧
EstimatedRTT)→ 再更新 EstimatedRTT → 最后 Timeout = EstimatedRTT +
4×DevRTT;
是默认值。 - 拥塞窗口演化:慢启动翻倍、拥塞避免 +1;超时 → ssthresh=cwnd/2,cwnd 归 1;三次重复 ACK → ssthresh=cwnd/2,cwnd=ssthresh+3 进入快速恢复,收到新 ACK 后回落到 ssthresh 继续拥塞避免;ssthresh 只有取值真变了才算一次"变化"。
- 发送窗口只有确认掉"最早未确认字节"才会滑动——中间有分组丢失时,即使后面的分组先到,窗口也会卡在缺口处不再前进。
- UDP demux 只看目的端口,可以多个客户端共用服务器同一个 socket;TCP demux 用完整四元组,每条连接对应服务器上一个独立的已连接 socket,即使本地端口相同也能靠对端 IP/端口区分。
上一篇 / 相关阅读
- Chapter 1(网络性能,Week 1–2):COMP5416 Kurose 交互题库题解:第一章
- Chapter 2(应用层,Week 3–4,期中范围):COMP5416 Kurose 交互题库题解:第二章
- 期中范围更正说明(Ed #22):Week 5 Transport 期中范围更正
- 考纲总览:COMP5416 Kurose 交互题库考纲对照指南
再提醒一次:本章内容是期末范围,期中复习可以先跳过,等期中考完再回来刷这一章即可。