一条链路标注 100 Mbit/s,另一个连接只能达到 10 Mbit/s。下载同一个大文件时,前者可能更快;只发送一个很短的请求时,两者的完成时间却可能接近。带宽描述单位时间内能够传输多少比特,请求完成时间还包含传播、处理、排队以及应用等待。仅知道一个速率,无法算出一次请求的总耗时。

第 00 篇已经区分发送接口返回、对端读取与应用回复。本篇把这些事件之间的时间拆开,先给一个能手算的存储转发模型,再改变报文数和到达间隔,观察排队怎样出现。所有例子中的速率、距离和时延都是模型输入,不是测得的公网性能。

先固定长度与时间的口径

设要发送的比特数为 L,链路串行发送速率为 R bit/s。一个比特占用发送器的时间是 1/R 秒,L 个比特依次进入链路需要 L/R 秒,这一项称为发送时延,也常称为串行化时延。

给定 L = 1500 × 8 = 12000 bit,R = 10,000,000 bit/s,得到发送时延 0.0012 s,即 1.2 ms。这里的 1500 字节被定义为模型每个报文的全部发送量。如果实际场景把 1500 字节定义为 IP 包长,链路首部、帧校验、前导码与帧间间隔等还需要另算,不能直接宣称 1.2 ms 是完整以太网占用时间。

数据的第一比特进入链路以后,还要沿介质传播。路径长度为 d,传播速度为 v,则传播时延为 d/v。设 d = 400 km,v = 200,000 km/s,单程传播为 2 ms。这两个数只是便于计算的设定,不代表某条实际光纤的长度和折射率。真实线路可能绕行,实际路径应由测量和拓扑资料支持。

发送时延关注报文有多长、发送器有多快;传播时延关注路径有多远、信号传播有多快。把 R 提高十倍不会直接改变 d/v。若将速率改为 100 Mbit/s,发送时延降到 0.12 ms,传播仍为 2 ms。第一比特更早进入线路不等于它在介质中的传播速度提高了。

时间起止点也必须固定。下文的单包完成时间从源端开始发第一比特算起,到目的端收到最后一比特为止。若从最后一比特发出开始计时,就不再包含源端这一段发送时延。RFC 7679 §3.4对 IP 单程时延使用明确的比特边界;设备测试中的 latency 又可能采用另一套边界,不能把不同定义的数据放进同一张比较表。

一个报文经过三条链路

设路径包含源端 S、两个中间节点 A、B 和目的端 D。三条链路均为 10 Mbit/s,每条传播时延均为 2 ms;每个报文 1500 字节,中间节点收到完整报文后才开始向下一条链路发送。这个前提叫存储转发。

1
S -- 10 Mbit/s, 2 ms --> A -- 10 Mbit/s, 2 ms --> B -- 10 Mbit/s, 2 ms --> D

暂时假设没有其他流量、没有处理开销、没有丢包,而且各节点可以在不同接口上同时接收和发送。第一条链路需要 1.2 + 2 = 3.2 ms。A 得到完整报文后再经历一次相同的过程,B 同样如此,所以最终时间是 3 × 3.2 = 9.6 ms。

这三个发送时延不能漏掉。在存储转发模型里,下游发送必须等待上游接收完成。如果设备能够在未收齐整帧时开始转发,时序就不同;那需要另建直通转发模型,不能沿用本算式。RFC 1242 §3.8正是通过不同起止点区分存储转发和位转发设备的测试语义。

现在只把三条链路全部改成 100 Mbit/s。单链路变为 0.12 + 2 = 2.12 ms,三条链路共 6.36 ms。速率提高十倍,但这个小报文的完成时间从 9.6 ms 降到 6.36 ms,没有降到原来的十分之一。剩余的传播时间在这个模型中占了六毫秒,单靠提高发送速率无法消掉它。

如果已知量只有长度、速率和传播距离,这些算式给出的是当前模型的无排队、无处理基线。现实请求还可能等候服务端线程、磁盘读取或应用限流。那些时间不在已知量中,不应通过“再乘一个经验系数”伪装成可靠预测。

连续报文可以重叠使用链路

十个报文依次经过三条链路时,不能把单包时间 9.6 ms 乘十。A 向 B 发送第一个报文期间,S 可以继续向 A 发送第二个报文;传播期间也不要求发送器空闲。不同报文在不同链路上的工作可以重叠。

在链路等速、报文等长、源端连续发送且缓冲足够的模型中,第一个报文耗时 H × (s + p),后续每个报文再增加一个发送时延 s。其中 H 是链路数,s = L/R,p 是每条链路的传播时延。N 个报文全部到达的时间因此为:

1
T = H × p + (H + N − 1) × s

代入 H = 3、N = 10、p = 2 ms、s = 1.2 ms,得到 6 + 12 × 1.2 = 20.4 ms。模型传输了 15,000 字节,对这个有限传输区间计算的平均速率约为 5.88 Mbit/s,仍低于链路标称 10 Mbit/s,因为计时包含开始阶段和传播尾部。它是由公式导出的平均值,不是运行脚本所测得的吞吐。

当 N 很大,固定的开始与传播开销被更多数据分摊,长时间平均速率才逐渐接近瓶颈速率。短请求与长文件因此可以有完全不同的瓶颈。若链路速率不相同,就要按各节点的到达与服务完成时间递推,不能盲用等速公式。

“带宽”还可能指链路容量、路径容量、可用容量或某层的观测速率。RFC 5136 §2.3将这些口径分开。某条路径即使包含高速链路,也会受较慢链路限制;已有流量又会改变可用份额。标称速率不能直接当成某个应用随时独占的额度。

排队从到达和服务的不匹配产生

对一个单出口 FIFO 队列,设第 k 个报文到达时刻为 a[k],服务开始时刻为 b[k],服务完成时刻为 f[k],每包发送时延都是 s。若服务不可抢占,则有:

1
2
3
b[k] = max(a[k], f[k−1])
f[k] = b[k] + s
q[k] = b[k] − a[k]

q[k] 就是等待开始发送的排队时间。模型初始队列为空,第一包在零时刻到达。如果报文间隔为 2 ms,而 s = 1.2 ms,则每包到达前上一包已经发送完成,等待始终为零。传播是否已经完成不会妨碍这个出口发送下一包。

将到达间隔改为 1 ms,发送器每包却需要 1.2 ms。第一包不等待,第二包等 0.2 ms,第三包等 0.4 ms,第十包等 1.8 ms。这个有限序列在附件中用精确分数计算,结果可逐项核对。

在持续无限输入、无限缓冲的理想化设定中,积压会继续增长;真实设备缓冲有界,最终可能丢包或触发其他控制。有限十包模型没有实现丢包、主动队列管理、优先级或发送端反馈,所以不能从输出宣称某种真实 TCP 算法已经表现出了相同排队曲线。

若报文前面有 n 个完整的等长报文,且没有正在发送报文的剩余部分,等待可简化为 nL/R。若前一包已经发送一半,或队列中报文长短不同,应使用前方剩余工作量计算。平均到达速率也不能唯一决定等待:相同长期平均速率下,一次突发十包与均匀分散到达会产生不同的队列。

RTT 与带宽时延积

RTT 是一个往返观察量,但测试仍需说明从哪个事件计到哪个事件。应用一次请求的耗时可能包括服务端业务处理;TCP 的确认往返又受确认策略和网络状态影响。两者都不能只凭名称就视为纯传播时间。

单向路径、容量、排队和处理可能不对称。测得 RTT = 40 ms,并不自动得到两个方向各 20 ms。跨主机直接比较发送与接收时间戳,还要考虑时钟偏移、分辨率和时间戳所在位置。RFC 7679 §3.7给出了这些误差来源的分析框架。

在持续发送并由反馈推进的模型里,如果发送速率为 R,一个往返期间送出的比特数约为 R × RTT。这就是 TCP 吞吐讨论中常用的带宽时延积估算。取 10 Mbit/s、40 ms,得到 400,000 bit,换算成 50,000 byte,约 48.83 KiB。这里使用十进制 Mbit/s,字节量除以八。

这个 50,000 字节表示在往返反馈尺度上维持相应发送速率所需的在途量级,不是某条单程物理链路的存储容量。讨论传播线上已有多少比特时可能用单程传播时延;讨论确认驱动的窗口时用 RTT。两个式子形式相同,时间变量的意义却不同。

若教学发送器最多允许 W = 10,000 字节未确认数据,而且每轮反馈需 40 ms,在充分供数且没有其他开销的简化窗口模型中,平均速率上界为 W/RTT = 250,000 byte/s,即 2 Mbit/s。链路有 10 Mbit/s 容量也不能使这个窗口自动变大。

RFC 6349 §3.3.1在吞吐测试语境中使用瓶颈带宽和 RTT 计算窗口需求。窗口满足 BDP 只消除一种限制,并不保证达到目标吞吐:发送端是否有数据、拥塞控制是否允许发送、接收端处理和丢失恢复都会影响结果。第 18–20 篇再分别处理接收窗口、拥塞窗口与排队。

吞吐和有效吞吐怎样计数

本篇把“观测吞吐”写成某一层统计的字节数除以观测区间,把“应用有效吞吐”限定为成功交付的唯一应用负载字节数除以同一区间。重传的重复字节、协议首部和无关数据不计入后者。实际工具可能采用其他口径,报告必须说明分子和分母。

假设应用成功获得 1,000,000 字节,期间链路发送了额外首部与重复数据。链路字节计数增大,并不意味着应用拿到了更多唯一内容。把网卡计数器与应用文件大小混用,会使一个看似更高的吞吐结果掩盖无效传输成本。

RFC 1242 §3.17中的 throughput 是特定设备测试术语,强调不丢失所提供帧时的最大速率;不能把这个定义直接贴到浏览器的下载速度上。RFC 5136 对容量与传输度量的区分可用于选定口径,但本篇“应用有效吞吐”的具体分子是此处明确约定的。

可复跑的手算检查

从仓库根目录执行:

1
python3 source/_posts/2026-09-19-计算机网络01-带宽高为什么仍然慢/model.py

程序使用 Python 标准库 fractions.Fraction,避免用浮点近似掩盖单位错误。源文件为 model.py,实际输出保存在 result.json。字段 evidence_type 明确标为精确算术模型,程序没有创建 socket,也没有测量脚本执行时间作为链路时延。

本次运行验证了五组结果:单包发送时延 6/5 ms;三链路单包 48/5 ms;三链路十包 102/5 ms;十包排队等待从 0 到 9/5 ms;40 ms RTT 对应的 BDP 为 50,000 字节,10,000 字节窗口上界为 2 Mbit/s。分数是计算结果,不是测量仪器的精度声明。

练习

练习一:改变长度。 将报文改成 500 字节,保持三条 10 Mbit/s 链路、每段 2 ms 传播和存储转发。计算一包与十包的全部到达时间。如果漏算两个中间节点的发送时间,误差是多少?

核对:每包发送 0.4 ms,一包共 7.2 ms,十包共 10.8 ms。只对单包漏算两个中间发送阶段,会少算 0.8 ms。十包不能沿用单包误差简单乘十,因为链路工作存在重叠。

练习二:构造平均速率相同的反例。 在二十毫秒观察窗口中发送十个等长报文,一组每隔 2 ms 到达,另一组全部在零时刻到达。服务时间仍是 1.2 ms,比较最大等待。再说明为什么这不能证明真实设备缓冲足够。

核对:第一组最大等待为零,第二组第十包等待 10.8 ms;二者在指定窗口内的到达总量相同。模型允许十包全部排队,而真实设备缓冲大小没有给定,因此丢包结果未知。

验证边界与一手资料

2026-09-19 在 Python 3.14.4 上运行附件,算术断言通过。本篇交付的是手算与确定性队列模型;没有运行 Linux 流量整形、空载/负载链路对照,也没有测量 NIC、TCP 窗口或公网 RTT。真实排队策略的对照需要专用 Linux 虚拟机或隔离命名空间,并在第 19–20 篇记录配置与观测。不能将这里的分数输出填入实测性能表。

以下资料在写作当次核查。RFC 1242、5136、6349 是 Informational 文档,提供术语或测试框架,不构成所有实现的统一性能承诺。RFC 7679 给出单程时延度量;本文的等速串行化与 FIFO 递推是明确假设下自行推导的教学模型。