简介:这份PDF是《计算机网络》第五章“传输层”的配套习题答案,面向计算机、网络工程等专业学生及考研备考者,适合课后自测、章节复习与考前冲刺使用。资源为1个PDF文件,压缩包仅23KB,打开即用;目前已有2643人学习。答案覆盖5-01至5-21等多道课后习题,逐一解析运输层在协议栈中的地位、运输层与网络层通信区别、复用概念、TCP与UDP的本质差异、VOIP为何采用UDP、端口分类与作用、伪首部校验和用途、UDP与IP能力差异、分片与重组的标识符机制等核心问题,并给出UDP数据报首部字段计算、以太网下数据报片长度与片偏移值等典型算例的具体求解过程。能帮助读者理清传输层脉络,掌握高频考点与计算方法,快速定位薄弱环节,提升解题准确性,是期末复习和考研备考阶段查漏补缺的实用资料。
1. 抱着“计算机网络第五章习题答案.pdf”啃,为什么越啃越慌
考前一周拿到这份“计算机网络第五章习题答案.pdf”,第一反应是想背。但有经验的过来人都知道:第五章如果只按答案背,最大的风险不是背不熟,而是背错方向。这个章节在绝大多数经典教材里落在传输层:TCP 校验和怎么算、超时重传的时间怎么估计、拥塞窗口怎么画,这些题换一个数字、换一次丢包位置,完全就是一道新题。PDF 能给你标准结论,给不了你推演过程。这篇文章用来补齐这段缺口:把答案里的计算题用 Python 重跑一遍,把状态图用 Wireshark 抓包验证一遍,再盘一盘最常见的掉分点。适合两类人:马上要考《计算机网络》期末、准备考研 408 基础复习的人,以及工作中要补 TCP 基础的运维和开发。
2. 先把答案当“考情地图”读:第五章的题型密度与复习取舍
一份没有题目的答案解析,其实可以反推出题人的意图。第 5 章在谢希仁《计算机网络》这类经典教材里讲的是传输层,题型的分布极其稳定:概念题考定义和参数,计算题考公式推导,看包题考状态机,问答题考“为什么”,综合题考多段连接叠加。把这些题型按分数权重排个序,就能决定你到底是花一个晚上背书,还是花三个晚上刷计算。
2.1 五类常考题型的应对策略:哪类题决定你能不能过
第一类是概念选择题,集中在端口号、TCP 标志位、UDP 特点、MSS 的含义。这类题靠熟记,不需要推导。注意端口号分段:0 到 1023 是知名端口,1024 到 49151 是注册端口,49152 到 65535 是动态端口。很多填空题会把端口范围当作送分题,反而丢分最冤。
第二类是计算题,这才是第五章真正的分水岭。必考三个方向:TCP 校验和的反码求和、加权平均 RTT 与超时重传、拥塞窗口的慢启动和拥塞避免。难点在于数字一换,过程不变,但结果和步骤顺序容易乱。这类题需要把每一步写清楚,不是背答案能解决的。
第三类是看包分析题,给一个时序图,问你哪个报文触发了重传,发送窗口是多少,已确认字节数是多少。这类题的核心是把 ACK 序号的含义吃透:ACK 序号代表“下一个期望收到的字节序号”,在计算时先明确这个前提,否则连第几个报文段是重传的都会看错。
第四类是主观简答,比如“为什么三次握手不能改成两次”“为什么 TIME_WAIT 要等 2MSL”“TCP 为什么要进行拥塞控制而 UDP 不关注拥塞”。这些题考的是表达能力,答案里的几句话背下来容易,面试时被追问一句“如果网络延迟极端大呢”就可能卡住。
第五类是综合题,把发送窗口、接收窗口、拥塞窗口放在同一个传输过程中。这类题最接近真实网络行为,也是最值得用模拟工具来验证的。如果你能把一段 Python 模拟跑通,就再也不会怕这种“窗口套窗口”的题目。
2.2 答案倒推复习清单:把“看懂”变成“能讲”
我的做法是,拿到答案 PDF 后先不记答案,而是做一次倒推:每道题都问自己三个问题——这题考的是哪个公式或协议行为;如果题目里的参数从 16 换成 32,计算过程哪些步骤会变;如果我是老师,我会把哪个关键步骤当作扣分点。
比如一道计算题答案里出现“ssthresh = 16”,倒推过程就要问:为什么慢启动到 16 就停?因为中间发生了丢包事件,拥塞窗口减半。这个事件是丢包序号决定的。再比如答案里写“EstimatedRTT = 121.05”,就要问:用的阿尔法系数是多少?是 0.125 还是教材给的其他经验值。不同教材对初始 RTT 的取值有不同假设,倒推时把这句写上,胜过抄十遍公式。
把答案倒推完成之后,整理成一张知识点清单,格式如下:知识点对应公式参数对照、真实抓包验证方式、易错的位置。这张清单不需要很长,但每一行都要能回答“为什么”。做完这个动作,PDF 就不再是黑匣子,而是一张可以随时往里补充的复习地图。
3. 用 Python 把答案里的计算题跑一遍:别让公式停留在纸上
3.1 TCP 校验和手工验证:反码求和与进位回卷的 20 行代码
校验和是第五章出现频率最高的计算题,也是手算最容易翻车的点。很多人按普通求和算完就取反,结果和标准答案差 1,原因是漏掉了“进位回卷”。TCP 校验和计算分两步:先把伪首部和 TCP 报文段按 16 位一组做二进制反码求和,再把结果取反。反码求和的要点是,每次相加若产生超过 0xFFFF 的进位,必须将它回卷加到低位。下面这段代码展示了这个机制:
import struct def checksum_core(data: bytes) -> int: """输入已经拼好的伪首部+TCP报文段,返回16位校验和""" if len(data) % 2 == 1: data += b'\x00' # 奇数长度补一个零字节,保证按16位对齐 total = 0 for i in range(0, len(data), 2): word = (data[i] << 8) | data[i + 1] total += word total = (total & 0xFFFF) + (total >> 16) # 关键:把进位回卷 return (~total) & 0xFFFF # 构造一个最简单的伪首部:源IP+目的IP+协议号+TCP长度 pseudo_header = bytes([ 10, 0, 0, 1, # 源 IP 10.0.0.1 10, 0, 0, 2, # 目的 IP 10.0.0.2 0, 6, # 0 是保留位,6 是 TCP 协议号 0, 20 # TCP 报文段长度 20 字节 ]) tcp_segment = bytes(20) # 假设 TCP 头全为 0,便于对照结果 result = checksum_core(pseudo_header + tcp_segment) print(f"校验和 = 0x{result:04x}")这段代码里真正不能省的是这一行:total = (total & 0xFFFF) + (total >> 16)。每加一个 16 位字,都可能让 total 超过 0xFFFF,超过的部分才是需要回卷的进位。不写这一行,结果基本都会和标准答案对不上。另一个容易误解的是字节序,教材里的算法都是把每 16 位按“高字节在前”组合,这在 x86 电脑上直接读抓包文件时需要先做一次顺序转换,否则跨平台验证又是新坑。
3.2 超时重传时间计算:RTT 加权平均与 RFC 6298 的落地代码
第五章另一道必考计算是 EstimatedRTT 和超时时间 RTO。教材给出的公式是:EstimatedRTT = (1 - α) × 旧EstimatedRTT + α × 新样本RTT,α 通常取 0.125;DevRTT 用 β = 0.25 做指数加权平均;最终 RTO = EstimatedRTT + 4 × DevRTT。考试时数字少,手算没问题;但如果你想验证自己的手算顺序,可以直接用这个函数:
def compute_rto(samples, alpha=0.125, beta=0.25): """按 RFC 6298 计算 RTO,samples 是按顺序到达的 RTT 采样""" if not samples: return None srtt = samples[0] # 第一个样本直接作为初始 RTT rttvar = samples[0] / 2 # 初始 RTTVAR 取样本的一半 for sample in samples[1:]: rttvar = (1 - beta) * rttvar + beta * abs(srtt - sample) srtt = (1 - alpha) * srtt + alpha * sample return srtt, rttvar, srtt + 4 * rttvar samples = [106, 120, 140, 90, 115] srtt, rttvar, rto = compute_rto(samples) print(f"EstimatedRTT={srtt:.2f}, DevRTT={rttvar:.2f}, RTO={rto:.2f}")参数说明:alpha决定新样本对平滑 RTT 的影响程度,0.125是标准实现;beta用于平滑偏差,标准是0.25。初始化方式很关键,第一个样本直接作为srtt,rttvar取样本的一半,这是 RFC 里的建议,考试时如果题目给的是“开始没有历史值”,就按这个逻辑算。手算翻车的同学,十有八九是把rttvar的初始值写成了 0,导致前几步 RTO 偏小,后半题全部连锁错掉。
3.3 拥塞窗口演进模拟:慢启动与拥塞避免的分水岭在 ssthresh
拥塞窗口计算题通常是给一段传输过程,要求你画出 cwnd 曲线。难点不在公式,而在时机:慢启动阶段每收到一个 ACK,cwnd 加 1,所以每个 RTT 近似翻倍;到达 ssthresh 或发生丢包后进入拥塞避免,每个 RTT 只加 1。模拟代码不需要复杂,重点是把“丢包事件”正确插进时间线:
def cwnd_timeline(loss_seq: int, init_ssthresh: int = 16, total_seq: int = 30): cwnd = 1 ssthresh = init_ssthresh for seq in range(1, total_seq + 1): if seq == loss_seq: ssthresh = max(2, cwnd // 2) # 丢包后阈值减半 cwnd = 1 # 重新从慢启动开始 print(f"seq={seq} 发生丢包: ssthresh={ssthresh}, cwnd=1") continue if cwnd < ssthresh: cwnd += 1 # 慢启动:每一个 ACK 加 1 MSS else: cwnd += 1 / cwnd # 拥塞避免:一个 RTT 约加 1 MSS print(f"seq={seq}: cwnd={cwnd:.2f}, ssthresh={ssthresh}") cwnd_timeline(loss_seq=10, init_ssthresh=16, total_seq=20)这个模型把 ACK 到达粒度简化成了“每个序号代表一次 ACK”,足以应对课本里的大部分画图题。参数loss_seq是丢包发生在第几个报文段,init_ssthresh是初始阈值。最容易算错的情况是:丢包发生时,cwnd 到底按多少减半?答案是用发生丢包瞬间的 cwnd,而不是丢包前的历史峰值。代码里先取当前cwnd // 2,再重置为 1,顺序不能反,否则 ssthresh 会算成一个过于乐观的值。
4. 在真实环境里把第五章的答案验证一遍:抓包与状态机
4.1 最小抓包实验:nc + tcpdump 复现三次握手
学习传输层最怕的就是把理论图和真实报文对不上。用一台 Linux 机器,不用写任何代码,就能看到三次握手。开三个终端,终端一执行监听,终端二发起连接,终端三抓包:
# 终端 1:监听本地 12345 端口 nc -l 12345 # 终端 2:发起连接 nc 127.0.0.1 12345 # 终端 3:抓 loopback 网卡,只看 12345 端口流量 sudo tcpdump -i lo -nn -S port 12345-i lo指定抓回环网卡,因为客户端和服务端都在本机;-nn不做 IP 和端口反解,避免 DNS 干扰;-S显示绝对序号而不是相对序号,方便和教材里的 seq 对应。抓到的结果应该有三行:第一行Flags [S]是客户端的 SYN,第二行Flags [S.]是服务端的 SYN+ACK,第三行Flags [.]是客户端最后的 ACK。注意第三行的 ACK 序号是“服务端序号 + 1”,而客户端自己的 seq 不会再增加。把这三行和课本上的握手图对照,比背十遍图都管用。做完这个实验,可以把第三个 ACK 的 seq 值和第二个包的 seq 对比,肉眼确认“这个包消耗了一个序号,第三个包没有消耗新序号”,这是看包题最喜欢考的点。
4.2 用 Python socket 走一遍完整连接:观察状态转换
三次握手只是建立连接的一部分,考试还会考正常关闭的四个报文。用一段 Python 就能看到主动关闭方进入 TIME_WAIT 的行为:
import socket, time # 服务端 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(("127.0.0.1", 9001)) server.listen(1) conn, addr = server.accept() conn.recv(1024) conn.close() server.close() # 客户端 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(("127.0.0.1", 9001)) client.send(b"hello") client.close()把这段代码按先后顺序拆到两个.py文件里跑,客户端执行close()后会立刻打印“连接已关闭”,但操作系统里这个 socket 还会停留在 TIME_WAIT。验证方法是在终端执行ss -tan | grep 9001,你会看到客户端那一端的连接状态是TIME_WAIT,而不是彻底消失。这个现象解释了一道经典简答题:TIME_WAIT 不是立刻释放,而是等 2MSL 后才消失,为的是让最后的 ACK 有机会在网络上补发。
recv(1024)这一行是关键,它保证服务端先收到客户端的数据,然后再关闭。如果服务端没调用recv就直接close(),可能触发 RST,状态序列就完全不同,考试里说的“四次挥手正常序列”就看不到了。真实抓包中 RST 的触发条件远比课本复杂,这也是很多同学在tcpdump里看到的挥手包数量和教材对不上的主要原因。
4.3 在 Wireshark 里读窗口字段:把流控从公式变成可见数字
Wireshark 是验证滑动窗口计算的最好工具。打开一个抓包文件,选中任意一个 TCP 报文,在中间的协议树里找到“Window”字段。这个字段就是接收方当前还能接收的字节数。考试题经常让你算有效窗口大小:有效窗口 = min(拥塞窗口,接收窗口)。抓包里能直接看到的是接收窗口,拥塞窗口是本机维护的内部变量,抓不到,但可以通过传输速率变化间接推断。
另一个值得看的是 Window Update 报文。当你看到一连串数据传输中突然插入一个没有载荷的 ACK,并且它的 Window 字段比你上一个看到的数值变大了,这就是接收方在告诉发送方“缓冲区腾出空间了”。考试里有时会把这种报文误认为“零窗口探测”,区分方法是看窗口值是否从 0 变成一个正数。零窗口通知的 Window 值为 0,随后发送方会定时发送 1 字节探测报文。把这个流程在抓包里走一遍,第五章流量控制的选择题基本不会再错。
5. 避坑:别把答案 PDF 背成自己的黑匣子,5 个最常见的翻车点
5.1 现象:答案和教材版本对不上,主观题不敢照抄
有些同学的答案 PDF 是从网上随便下的,结果发现里面的第五章讲的是“应用层”或“数据链路层”,而自己的教材第五章是“传输层”。原因很简单:不同版本的教材章节划分不同,比如谢希仁版第五章是传输层,而《计算机网络:自顶向下方法》的中文改编版可能把链路层排在第五章。
解决:先对照课程大纲确认这本书的第五章主题。如果主题对不上,只提取 PDF 里关于 TCP、UDP、端口、拥塞控制的题目,其余直接忽略。科目复习最怕的是把知识体系搭在错误的地基上,这一条不解决,后面所有答案都可能是在背无关内容。
5.2 现象:手算 TCP 校验和,结果和答案总是差 1
表现是算出来的校验和是0xFFFE,答案写0xFFFD,反复检查普通加法也没错。原因通常是漏了进位回卷,或者把伪首部里的协议号写成了十进制 6 但没有填充到 16 位字的高字节。伪首部不是真的 TCP 报文,它不参与传输,但必须参与校验和计算,这一条在题目的字缝里经常被忽略。
解决:按照“每加一个 16 位字,立刻把溢出位移回低位”的顺序来,不要等全部加完再统一进位。再用上面的 Python 代码对一遍,确保伪首部里的每个字段都按 8 位一组拼好。检验自己的计算,只需要把结果里两端的 0 和 F 对调,如果有进位遗漏,结果通常表现为某一位差 1。
5.3 现象:拥塞窗口曲线画出来比答案大一倍
很多同学把慢启动理解成“每个 RTT 窗口翻倍”,画图时从 cwnd=1 跳到 2、4、8,这没错。错的是把“收到一个 ACK 窗口加 1”写成了“收到一个报文段窗口加 1”,或者把快速重传后的处理顺序写反。
解决:画图之前先确定两个事件:一是丢包报文段的序号,二是丢包时 cwnd 的实时值。这两个数决定 ssthresh 的新值是多少。快速重传阶段执行的是 cwnd = ssthresh + 3,而超时重传阶段执行的是 cwnd = 1,这两种重置方式在答案里的曲线形态完全不同。拿到题目先看“这里用的是快速重传还是超时重传”,再决定起点。
5.4 现象:发送窗口和接收窗口混在一起算
题目给了一个 16KB 的接收窗口,又给了拥塞窗口 8KB,不少同学直接把发送窗口算成 24KB。实际上发送窗口不是“加起来”,而是取最小值:有效发送窗口 = min(拥塞窗口,接收窗口)。TCP 流量控制的核心是不要超过接收方的处理能力,拥塞控制的核心是不要压垮中间链路,两个限制取交集,而不是叠加。
解决:做题时在草稿纸上画两条数轴,一条标拥塞窗口,一条标接收窗口,发送方可用量永远是两个窗口覆盖范围的重叠区域。真实抓包里,Wireshark 显示的 Window 字段就是接收窗口,你可以主动设置一个很小的SO_RCVBUF再抓包,接收窗口字段会立刻变小,这个实验能帮你把公式彻底落到直觉上。
5.5 现象:TCP 状态图背得熟,换一个场景就排错顺序
状态转换图考得最多的是主动打开方和被动打开方各自走哪条路径。背书时觉得都记住了,一做题把 SYN_SENT 和 SYN_RCVD 混在一起。原因是图中把所有角色画在了一张状态图里,实际执行时一台设备只会走其中一半路径。
解决:用手画两列状态,左边是主动方,右边是被动方。主动方从 CLOSED 出发,依次经历 SYN_SENT、ESTABLISHED、FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT;被动方从 LISTEN 出发,经历 SYN_RCVD、ESTABLISHED、CLOSE_WAIT、LAST_ACK。每次做题只填一列,不要把另一列的状态混进答案。复试被导师追问时,这一列一列画出来的功力,远胜过背整张图。
6. 把答案变成自测夹:一张表格在 20 分钟内复盘第五章
答案 PDF 的价值不在于让你“见过题”,而在于让你“能复现”。我的习惯是:每周挑出答案里的五类题各一道,不看原题,只看自己整理的结论,然后按下面的表格做一次快测。
表格从左到右五列:题型、考点、公式或状态、参数、易错点。比如第一行填写“校验和”,考点写“反码求和+伪首部”,参数写“每 16 位一组,进位回卷”,易错点写“漏掉伪首部”。第二行填写“拥塞控制”,考点写“慢启动 vs 拥塞避免”,参数写“ssthresh 减半”,易错点写“丢包时 cwnd 的实时值取错”。五分钟内能不看 PDF 把这张表填完,说明这章的知识结构已经进入长期记忆;填不出来,就回到对应章节的 Python 代码或抓包实验重新跑一遍。
这道自测的进阶玩法是“改参变题”:把答案里所有数字改掉,比如把 RTT 样本从 106、120、140 改成 200、180、220,用自己的 Python 函数重新算一遍,再和 PDF 里原题的思路比对。如果改参之后你依然能说出每一步在干什么,那考场上的任何数字变化都无法难住你。这套方法我带给过不少备考的学弟学妹,对期末、对考研 408 里的计算机网络题目都适用。
真实工作里排查网络问题时,第五章这些知识同样派得上用场:一次线上接口偶发超时,经验不够的工程师只会看应用日志,而传输层基础扎实的人会先去抓包确认是重传超时还是窗口缩小。答案 PDF 只是入门的门票,把每个数字亲手算过、每段状态亲手抓过,才算真正把这一章变成自己的工具。希望这些方法能帮你在考前少走一段弯路。
本文还有配套的精品资源,点击获取