引言

在进行TCP下载的时候, 观察网络, 会发现同时会有"很大"的上行, 比如我的Steam下载

image-20250303195838136

下载速度大概为1000Mbps的时候, 我会产生20Mbps的上行.

同时qBittorrent的[Options]-[Speed]中有一个选项[对传送总开销进行速度限制] image-20250303200101280

在开启了这个选项, 并且设定一个小于你最大上行的速度限制后, 会发现当你下载速度变高后, 其他种子的上行会随之降低.

这些现象为什么发生, 是本文要探讨的内容.

TCP

无论是HTTP下载, 还是BT下载, 所依赖的都是TCP协议. 要了解上述现象, 就要先了解这些行为所依赖的协议.

根据RFC的定义, 当我们下载的时候, 每当Server端发送给我们一个TCP报文段, 我们就要回应一个没有数据的TCP报文段(ACK)表示已经完全收到并请求下一个报文段(暂且不考虑Cumulative Acknowledgment和Delayed Acknowledgment).

举例

具体举例来说:

本地网络设置的MTU是1480, 则Server端TCP报文中, 最大的数据量+TCP头信息就为1480字节.

使用iperf3进行测试(IPv4)

image-20250303215414519

Server端发送给我们的内容则为:

名称报文大小说明
数据1480-32=1448MTU限制了最大数据
IP头20
TCP头32因为包含了OPTION, 所以变大了
Eth头14目标MAC, 源MAC, 以太网类型

则我们接收到的一个TCP包大小为1480+20=1514Byte, 但因为MTU限制, 所以最终为1480Byte.

我们的ACK只会包含TCP头,IP头,Eth头, 而不会包含数据, 所以ACK的大小为32+20+14=66Byte.

则我们的上行速率会是实际下载数据速率的$\frac{66}{1480}=4.459459459\%$

这是在每一个ACK包都对应了一个TCP包情况下的最大占用上行.

在实际的网络请求中, 我们会有累积确认 (Cumulative Acknowledgment)和延迟确认 (Delayed Acknowledgment), 这两种机制会使得我们的ACK包的数量小于接收到的TCP包的数量.

累积确认: TCP 使用累积确认机制, 这意味着接收方发送 ACK 时通常确认的是某一个数据序列号之前的所有数据. 例如, 如果接收方收到序列号为 1 到 100 的数据包, 它可能只发一个 ACK 来确认到 100 序列号为止的所有数据.

延迟确认: 为了减少 ACK 包的数量, 许多 TCP 实现使用延迟确认(Delayed ACK)策略, 等待一小段时间, 以期望可以用一个 ACK 包确认多个数据包.

通过Wireshark抓包我们可以看到

image-20250303213827378

1是服务器发送给我们的包的数量, 2是我们返回给服务器ACK的数量, 3是我们的下载速率, 4是我们的上传速率.

简单计算一下, 假设服务器给我们的包的大小大一样, 我们返回给服务器ACK包的大小也都一样.

那么如果我们每接收到一个TCP的包, 就返回一个ACK, 那么我们最终的上行速率会是 $$ 19*\frac{783360}{378459}=39.327483294Mbps $$ 根据上面的理论实际上行速率占比 $$ 947*4.459459459\%=42.2310810767Mbps $$ 产生误差是因为我们假设了每个包的大小都一致, 但TCP实际上有分片机制, 握手挥手机制, 导致了这个误差.

以上的这些都是在内网测试中的结果, 如果我们是通过PPPoE拨号上网, 则上行的包中还会包含PPPoE的8Byte.

结论

最后得到结论,

在MTU设置为1500Byte, 并且不考虑Cumulative Acknowledgment和Delayed Acknowledgment的情况下, 下载时, 上行所占比为

ACK头大小内网外网
最小20+20+14=54Byte
(TCP头20Byte, IP头 20Byte,Eth 14Byte头)
20+20+14+8=62Byte
(TCP头20Byte, IP头 20Byte,Eth 14Byte头, PPPoE 8Byte.)
最大60+20+14=94Byte
(TCP头60Byte, IP头 20Byte,Eth 14Byte头)
60+20+14+8=102Byte
(TCP头60Byte, IP头 20Byte,Eth 14Byte头, PPPoE 8Byte.)
内网外网
最小$54/1500=3.60\%$$62/1500=4.13\%$
最大$94/1500=6.26\%$$102/1500=6.80\%$

如果考虑了Cumulative Acknowledgment和Delayed Acknowledgment, 则大致将上述结果/2, 根据实验大概可得通常外网下载时, 上行所占比例为$3.6\\%-4.2\%$.

千兆宽带在千兆光猫为什么不能满速

同理我们也可以根据上文中的TCP报文, 得知, 为什么1000Mbps的宽带, 使用千兆光猫时测速结果最多是950Mbps.

千兆光猫的定义是最高理论传输速率为1000Mbps, 其中包括了数据量包括所有的头信息, 包含但不限于IP头, TCP头, 数据, ETH头等.

因为数据占总的包是 $$ \frac{1500-20}{1500+20+14+8}=0.9597924773 $$ 这是按照TCP头为20计算的, 如果更大的话, 则数据所占比会更低 $$ \frac{1500-60}{1500+60+14+8}=0.91024020227 $$ 平均下来大概就是$95\%$左右, 则我们实际的速度也就是$1000Mbps*95\%=950Mbps$左右.

PS

虽然学完计网之后脑子里面有意识到, 下行会产生一定的上行, 但一直没想过会占用多少上行.

为什么会突然想计算一下具体占比, 是前一段时间跑PT有点多, 一个月大概上传了1TB, 导致联通将我的上行从原本的50Mbps限制为了10Mbps, 限制了上行后, 发现我的Steam下载,HTTP下载均跑不满我的1000Mbps的带宽.

开始以为是光猫的光功率有问题, 检查没问题之后尝试了一下UDP测速, 发现下行是正常的, 才猛地想起来ACK会占用上行这个问题.