1. 为什么车载网络测试离不开 iperf3
这几年我大部分精力都花在车载以太网和智能座舱的网络性能验证上,手边几乎每天都要开着终端跑 iperf3。坦白讲,这工具不是那种装完看一眼就会放下的玩具,它是真正能帮你把网络问题量化出来的硬核家伙。无论是工程师评估一条 CAN FD 到以太网的网关转发能力,还是测试座舱域控制器与云端之间的 TCP 吞吐,iperf3 都是那个最常被点名、也最容易被用错的开源工具。
iperf3 的定位非常纯粹:通过客户端与服务端之间的双向数据流,测出链路能跑多快、延迟有多大、丢包有多严重。它不像 ping 只给个往返时间,也不像网盘下载那样受服务器和磁盘影响,iperf3 直接压满链路,让你看到这条网络在极限状态下的真实表现。对于车载环境来说,意义尤其大:车里的网络拓扑复杂,有交换机、有网关、有无线模块,每跳都可能成为瓶颈,而 iperf3 可以把瓶颈定位到具体一段链路。
这篇内容不是官方文档的翻译,也不是参数表的罗列,而是基于我在实际测试中跑出来的经验总结。从安装、基础用法,到 TCP/UDP 打流的关键参数,再到车载测试中如何设计脚本、如何解读结果,我都会尽量讲透。刚接触 iperf3 的测试工程师可以把它当作速查手册,老手也可以看看我在 UDP 抖动测试和 JSON 解析上有哪些坑踩出来的心得。
2. 装上 iperf3,就是一场说走就走的测试
2.1 各平台安装方式与版本区别
iperf3 的安装没什么难度,但有一个地方需要特别注意:新旧版本之间的兼容性。官方维护的 iperf3 目前主要停留在 3.x 系列,早期 2.x 和 3.x 的命令参数差异很大,而且 3.x 之间也存在小版本不兼容的情况。我在测试中通常固定使用 3.1.3 以上版本,客户端和服务端保持一致,否则很容易出现unable to connect to server: Connection refused或者握手后立即报错的情况。
先列一下我在 Ubuntu、Windows、Android 车机环境下的安装方式:
| 平台 | 推荐安装方式 | 备注 |
|---|---|---|
| Ubuntu / Debian | apt install iperf3 | 版本可能偏旧,如需 3.13+ 可源码编译 |
| CentOS / RHEL | yum install iperf3 或编译安装 | EPEL 源里通常有 3.9+ |
| Windows | 从官方或第三方编译版本下载 exe | 需要同时准备客户端与服务端两个 exe |
| Android 车机 | 使用 ToyVCN 或自行交叉编译 | 常见于车载 HIL 测试环境 |
| macOS | brew install iperf3 | Homebrew 安装很方便 |
在车载测试里最头疼的是 Android 系统。车机一般跑的是定制版 Android,很多没有 root 权限,也没法直接装 iperf3 的 APK 包。更常见的做法是找一台 Linux 工控机当作服务端,或者用支持 iperf3 的测试工具箱(比如网络测试工具箱 v8.4 / v8.6 这类集成工具)直接跑在 Windows 笔记本上。这类工具箱往往把 iperf3 的客户端和服务端打包好,还带了网卡限速、路由切换、抓包分析等功能,在产线上非常实用。
2.2 验证安装成功与最小化测试流程
装完之后先别急着上复杂参数,我习惯先跑一条最简单的命令验证环境:
# 服务端 iperf3 -s -p 5201 # 客户端 iperf3 -c 192.168.1.100 -p 5201服务端会进入监听模式,默认监听 5201 端口。客户端连上来之后默认做 10 秒的 TCP 测试,结束后客户端窗口会输出带宽、重传、MSS 等信息。如果这个流程能顺利跑通,说明基础环境没问题。这里要提醒大家一个细节:iperf3 默认在测试结束时会打印一条iperf done.的提示,有些脚本会用它来判断测试是否完成,但在自动化解析时更可靠的方式是捕获客户端的退出码,0 表示正常结束,非 0 表示测试异常。
我遇到最多的问题是防火墙。尤其在公司内部网络或者车间的网段里,Windows 防火墙默认会拦截 iperf3 的入站连接。解决方法很简单:要么以管理员身份放行 5201 端口,要么在测试时段临时关闭防火墙。但在产线上不建议关防火墙,最好加一条入站规则,只放行指定 IP 访问 5201 端口。
3. TCP 测试:吞吐量背后的关键参数和判定逻辑
3.1 为什么 TCP 测试默认只有 10 秒
很多刚接触 iperf3 的朋友会问:为什么默认测试时间是 10 秒?能不能拉长一点?其实这个默认值很有讲究。10 秒是一个平衡点,既能覆盖 TCP 慢启动和拥塞控制的完整过程,又不会让测试占用太久的带宽。但车载网络场景中,10 秒常常不够用。比如测试一条经过网关转发的链路,网关内部的转发芯片可能有缓存水线、队列调度策略,短时间测试很难暴露这些问题。
我更推荐在车载测试中把测试时间设置到 30 秒以上,特别是做稳定性验证时,可以用-t 300跑 5 分钟。长时间的 TCP 测试可以观察带宽是否出现周期性波动、重传率是否随温度升高而恶化。我曾经在舱内温度 80 度的环境舱里跑 10 分钟 TCP 流,结果第 7 分钟开始重传率从 0.1% 窜升到 2%,这才发现是 PCB 上的网络变压器在高温下性能衰减——这种问题只跑 10 秒根本测不出来。
TCP 吞吐量的计算公式说起来简单:吞吐量 = 接收窗口大小 / RTT。但 iperf3 内部还会维护发送缓冲区、拥塞窗口、MSS 大小等参数,最终结果反映的是整条路径的应用层吞吐上限。因此当你看到 TCP 带宽不稳定时,不要只盯着带宽数字,还要看重传率和接收窗口变化。iperf3 默认的-i 1间隔输出可以帮你捕捉到每秒的瞬时带宽。
3.2 影响 TCP 吞吐量的几个核心参数
在 iperf3 的 TCP 测试中,我最常用的参数有以下几项:
iperf3 -c <server-ip> -t 30 -i 1 -P 4 -w 2M -l 64K -O 5逐个解释一下:
-t 30:测试 30 秒,适合车载链路稳定性观察。-i 1:每 1 秒打印一次瞬时带宽,方便绘制曲线。-P 4:启用 4 个并行连接。每个连接独立维护拥塞窗口,并行可以提高吞吐上限,但也会放大丢包的影响。-w 2M:设置 TCP 窗口为 2MB。窗口大小直接限制链路上的在途数据量,尤其是高带宽长距离链路,默认窗口可能成为瓶颈。-l 64K:设置应用层读写缓冲长度。这个参数在某些内核版本上会影响实际 MSS 分割,不要轻易改动,除非你知道自己在做什么。-O 5:跳过前 5 秒的结果统计,避免慢启动阶段拉低平均值。
当测试车载以太网中 100M / 1000M PHY 到 SoC 之间的链路时,-P 4和-w 2M的组合能跑出接近线速的效果。比如我测过一块 NXP 平台的网关,单线程只能到 120Mbps,4 线程可以压到 920Mbps,8 线程已经到了 CPU 瓶颈。这个过程中,通过逐步增加并行数来观察 CPU 占用率的边际变化,可以初步判断瓶颈在硬件还是协议栈。
3.3 解读 TCP 测试报告的每个字段
TCP 测试结束后的输出类似这样:
[ ID] Interval Transfer Bitrate Retr [ 5] 0.00-30.00 sec 3.38 GBytes 968 Mbits/sec 3 sender [ 5] 0.00-30.00 sec 3.38 GBytes 968 Mbits/sec 0 receiverTransfer是这段时间内传输的数据量,Bitrate是平均带宽。Retr是发送端记录的重传次数。重传次数越少越好,但 0 重传在复杂拓扑里很难实现。sender和receiver的带宽差异反映了网络中是否有数据丢失或乱序。如果两者差距超过 5%,我一般会怀疑中间设备有丢包或者网卡驱动异常。- 上面的报告中
Retr 3但接收端没有丢包,说明重传发生在发送端,通常是缓存不足或早期拥塞窗口调整导致的,普通 TCP 连接无法避免。
我还习惯关注-i 1输出的每秒数据,尤其看有没有突然掉零或者翻倍的跳变。曾经有一次测试中,每秒带宽从 940Mbps 突然掉到 150Mbps,持续 3 秒又恢复,配合发送端的Retr从 0 变成 30,基本可以确定是对端网卡遇到了缓存溢出。
4. UDP 打流:测极限带宽、丢包率和抖动
4.1 为什么车载测试必须用 UDP
TCP 有重传机制,网络差的时候它会自动降低速度来保证可靠传输,但你无法精准控制链路要承受多大的压力。UDP 则正好相反,发多少就是多少,不关心对端是否收到。这就是 iperf3 做 UDP 打流的意义:用固定速率灌流量,观察链路真实承受能力。
车载网络中特别需要 UDP 打流的场景很多。比如音视频流的传输走的是 RTP over UDP,导航地图增量包虽然用 TCP,但很多厂商也用 UDP 做私有协议。如果链路在重负载下丢包率超过 1%,视频就会卡顿,远程控制指令就会延迟。iperf3 的 UDP 模式可以预先设定目标带宽,然后告诉你实际接收带宽、丢包率和抖动,这三个指标直接对应了音视频体验的三大核心参数。
UDP 测试还有一个好处是能测量抖动。TCP 因为重传和拥塞控制的存在,测出来的 RTT 波动并不完全是链路本身的抖动。UDP 模式下每个包都携带了时间戳,iperf3 可以根据接收端收到的包间隔计算出抖动值,这个值对于判断网关转发稳定性、交换机缓存深度很有参考意义。
4.2 UDP 打流常用参数与带宽决定方式
UDP 打流的命令和 TCP 类似,但必须显式指定带宽:
# 服务端 iperf3 -s -p 5201 # 客户端,向服务端打 100Mbps 的 UDP 流,持续 30 秒 iperf3 -c 192.168.1.100 -u -b 100M -t 30 -i 1-u启用 UDP 模式,-b 100M设置目标带宽为 100Mbps。如果不指定-b,iperf3 会默认设置一个很小的值(通常 1Mbps),测出来的结果几乎没有任何参考价值。所以跑 UDP 测试时,必须明确设置-b,这是新手最容易犯的错误。
针对不同的测试目的,-b可以这样取值:
- 链路标称带宽的 80%:模拟正常业务的负载上限。
- 链路标称带宽的 120%:过载测试,看丢包率如何增长。
- 固定小带宽(如 2Mbps):测试语音这类低码率实时业务的抖动。
另外-b还可以加后缀单位,比如-b 10M、-b 500K、-b 1g都支持。如果想要绝对精确地控制发包速率,可以在-b后加上:1,表示一次性发送指定数量后立即结束,比如-b 10M:2000表示每秒发 2000 个包,每个包的荷载根据带宽计算。
UDP 包大小也会影响测试结果。我的经验是,-l 1400适合模拟标准以太网 MTU 1500 下的有效载荷;如果测试的是车里的 V2X 消息,通常每包只有几百字节,可以用-l 500模拟小包突发。小包模式下 CPU 开销会急剧上升,因为每秒要处理的中断数量变多了,此时测到的带宽上限往往不是链路瓶颈,而是 CPU 收包能力的上限。
4.3 丢包和抖动的判读方法
UDP 测试结束后,接收端会输出这样一段报告:
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams [ 5] 0.00-30.00 sec 112 MBytes 31.4 Mbits/sec 0.045 ms 0/100135 (0%) receiver这里的Jitter是抖动值,单位毫秒,越小越好。Lost/Total Datagrams表示丢失包数 / 总包数,括号里是丢包率。需要特别强调的是,上面的示例显示发送端设了 100M 但接收端只有 31.4M,丢包却是 0,这种结果说明发送端实际没有发满 100M,可能因为 CPU 或调度问题没有达到目标速率。丢包为 0 时,如果接收带宽远小于目标带宽,问题往往出在发送端性能上,而不是链路上。
如果出现丢包,首先要看丢包率数值。车载以太网链路在正常工作状态下,UDP 打流丢包率应低于 0.01%。如果达到 1% 以上,基本可以判定链路存在瓶颈或配置错误。我遇到过一种情况:UDP 设定 500Mbps,丢包率 50%,但接收带宽稳定在 250Mbps。这说明链路或者对端只能处理 250Mbps,多的流量全部被丢弃。此时再配合 TCP 测试结果,就可以区分是链路带宽不够,还是对端 CPU/缓存不够。
抖动值的解读要结合测试时长。短时间(10 秒)测出的抖动往往比长时间更小,因为网络设备的调度策略有时间窗口效应。我建议至少测 60 秒,取平均值和最大值一起看。音频回放测试中,抖动超过 5ms 就能明显感知到声音断续,抖动超过 20ms 基本不可用。
5. 让 iperf3 更符合真实车载场景的进阶玩法
5.1 双向测试与优先级队列验证
默认情况下 iperf3 是单向测试,客户端往服务端打流量。但车载网络中的很多业务是双向的,比如 ADAS 数据回传与云端控制指令同时进行。要模拟这种场景,可以用-d和-r参数:
# 双向测试,同时进行上行和下行流量 iperf3 -c 192.168.1.100 -d -t 30 # 反向测试,仅测服务端到客户端的下行带宽,客户端不主动发流 iperf3 -c 192.168.1.100 -R -t 30-R模式特别有用,它可以排除客户端发送速率对结果的影响。在某些嵌入式平台上,发送路径和接收路径的驱动实现差异很大,同一链路双向带宽可能不对称。我曾经在一个车上测出上行 900Mbps、下行只有 300Mbps 的夸张差异,最后定位到是下行方向经过了另一台交换机,而该交换机的 QoS 策略把广播流量限速了。
如果要验证车载交换机的优先级队列,建议这样操作:先用 iperf3 UDP 打满背景流量,比如打 600Mbps 的背景流,再用另一路 iperf3 打高优先级视频流。此时观察高优先级流的丢包和抖动是否满足要求。iperf3 支持多个客户端同时连同一个服务端,你可以在两台电脑上分别跑不同优先级参数的 iperf3,服务端共用 5201 端口。注意,服务端默认支持多客户端并发,但每个客户端需要指定不同的--cport源端口以避免冲突。
5.2 测试时间与测试模式:-O跳过慢启动,-n固定数据量
TCP 慢启动导致的前几秒带宽不稳定,对追求极致吞吐的测试者来说是个噪音。-O参数可以跳过开头 N 秒再开始统计,这样最终的汇总结果更接近稳定状态。不过要注意,-O只影响统计,不影响实际数据流的发送。测试总时长依然是-t指定的时间,但统计区间是后半段。
如果你更关心传完指定数据量需要多久,而不是固定时间内的吞吐,可以用-n参数,比如传输 100MB 后自动结束:
iperf3 -c 192.168.1.100 -n 100M这在车载 OTA 升级场景中很有参考意义。OTA 包通常有固定大小,用-n 100M可以测出该大小文件的平均传输时间和实际吞吐,比固定时间测试更贴近真实业务。
除此之外,--get-server-output参数可以同时拿到服务端的报告。当怀疑服务端接收路径有问题时,这个参数能帮你对比客户端发送带宽与服务端接收带宽的差异。使用方式是:
iperf3 -c 192.168.1.100 --get-server-output输出内容会在客户端报告末尾追加一段服务端的摘要,包括服务端接收到的数据速率和丢包计数。
5.3 JSON 输出与自动化测试脚本的搭配
跑完测试后如果能拿到结构化的数据,喂给脚本分析、生成报告,效率会提升很多。iperf3 的-J参数会输出完整的 JSON 结构,里面包含发送端、接收端的所有统计信息。下面是一个 JSON 片段的结构示意:
{ "start": { "test_start": { "protocol": "UDP", "num_streams": 1, "target_bitrate": 100000000 } }, "end": { "sum_received": { "bits_per_second": 31457280, "jitter_ms": 0.045, "lost_packets": 0, "lost_percent": 0.0 } } }在车载测试中,我通常把 iperf3 的命令包一层 Shell 脚本,循环测试多个速率点,把 JSON 结果用 Python 或 jq 解析,提取出带宽、丢包率、抖动这三个关键值,然后写入 CSV 报表。这种做法的好处是把测试过程标准化,避免人为记录误差。
下面是我常用的一个批量测试脚本片段,这个脚本会依次测试 5 个 UDP 速率点,每个测 20 秒,最后汇总结果:
#!/bin/bash SERVER=192.168.1.100 for rate in 10M 50M 100M 200M 500M; do iperf3 -c $SERVER -u -b $rate -t 20 -J > ${rate}.json python3 -c " import json, sys data=json.load(open('${rate}.json')) end=data['end'] rx=end.get('sum_received', {}) print('${rate} => bitrate:', round(rx.get('bits_per_second',0)/1e6,2), 'Mbps, lost:', rx.get('lost_percent'), '%, jitter:', rx.get('jitter_ms'), 'ms') " done这样打完一排速率后,就能直观看出这个链路在哪个阈值附近开始恶化。如果你的测试系统里没有 Python,用 jq 也可以完成同样的提取:
iperf3 -c 192.168.1.100 -u -b 100M -J | jq '.end.sum_received.bits_per_second'5.4 多设备组网测试:从点对点到拓扑压力测试
单台客户端连单台服务端是最简单的测试,但车载网络是多节点互通的,真实场景下需要把多路流量汇聚到同一交换机的上行口。这种压力场景下,一台电脑跑一个 iperf3 进程往往不够,需要多台客户端同时向同一服务端打流。
我常用的部署方式是:
- 服务端放在核心交换机端口,使用
iperf3 -s -p 5201监听。 - 多个客户端分别连接到不同交换机端口,各自运行
iperf3 -c <server-ip> -u -b 100M -t 60。 - 服务端控制台会显示每个客户端的 IP 和吞吐统计。
- 观察上行口是否拥塞,以及交换机的丢包计数器是否增长。
这种组网测试可以验证交换机上行带宽、ACL 规则、VLAN 隔离是否正常。很多车载以太网交换机支持的 VLAN 优先级转发,在这种并发压力下才能暴露问题。如果服务端有多个网口,也可以分别绑定不同 IP 跑独立服务端实例,避免端口冲突。
不过在车载环境做这种测试要注意:车内的供电电流有限,多个设备同时满负荷工作可能会导致电压波动,个别 USB 转网卡设备会掉线。建议使用带独立供电的工业以太网转换器,或者给笔记本和工控机配 UPS,以免测试中途设备重启造成误判。
6. 高频问题排查实录与参数对照表
6.1 客户端无法连接服务端
典型现象:unable to connect to server或者Connection refused。我通常按下面顺序排查:
- 先确认服务端是否已经启动,
ps -ef | grep iperf3有服务端进程。 - 从客户端 ping 服务端 IP,确认二层三层可达。
- 确认端口没有被占用,用
netstat -anp | grep 5201查看监听状态。 - 检查防火墙和 SELinux,特别是 Windows 和 CentOS 系统。
- 如果服务器监听在
::IPv6 地址而客户端用 IPv4 连接,需要加-4参数强制 IPv4。 - 某些路由器开启了 AP 隔离,无线客户端之间无法互访,这种情况在有 WiFi 的车载测试环境很常见。
6.2 测试完毕但没有输出报告
区分两种情况:如果命令被执行但没有显示 Summary 就退出,大概率是Ctrl+C手动中断了。iperf3 会丢弃被中断的测试结果,不会打印最终汇总。另一种情况是平台差异导致控制台编码问题,在 Windows 中文环境里偶尔会出现输出乱码,但数据仍然是完整的。建议用-J输出 JSON,然后用工具解析,绕开控制台编码问题。
6.3 双向带宽不对称
如果-d双向测试结果差距过大,首先确认两端网卡是否都工作在相同的协商速率。用ethtool eth0查看实际协商结果,很多 USB 转百兆网卡会在驱动初始化时协商成 100M-Full,但实际收发只有 10M。其次看 CPU 核心数是否不足,iperf3 单线程可以跑满单核,双向测试需要至少两个核,建议用-A参数指定 CPU 亲和性。最后看交换机端口是否配置了速率限制或端口镜像,镜像端口也会影响收发吞吐。
6.4 多线程测试时吞吐反而下降
这是一个常见反直觉现象。有时-P 4比-P 1吞吐还要低,原因通常是接收端 CPU 处理不过来。每个流对应一个 socket,内核需要分配软中断处理每个数据包。当总包数每秒超过接收端 CPU 能处理的上限时,中断风暴会导致吞吐暴跌。解决方法:降低-l缓冲区大小、调大网卡 ring buffer、优化中断亲和性。在嵌入式车机上,建议先测单线程,再逐步增加并行数,观察 CPU 负载曲线。
6.5 参数速查表
为了方便日常查阅,我把核心参数整理成了一张速查表:
| 参数 | 作用 | 典型取值 | 使用心得 |
|---|---|---|---|
-s | 服务端模式 | 无 | 服务端默认端口 5201,可加-p指定 |
-c | 客户端模式并指定服务器 IP | 服务器地址 | 最常用参数 |
-u | UDP 模式 | 无 | 测丢包和抖动,必须配合-b |
-b | 目标带宽 | 10M/50M/100M/500M | UDP 必填,TCP 也可用但用处不大 |
-t | 测试时长 | 30/60/300 秒 | 稳定性测试建议至少 60 秒 |
-i | 每次结果的间隔 | 1 秒 | 绘制曲线时用-i 0或-i 1 |
-P | 并行连接数 | 1~8 | 先单线程,再逐步增加 |
-R | 反向模式 | 无 | 测下行,避免客户端发送影响 |
-d | 双向同时测试 | 无 | 适合双向业务模拟 |
-O | 跳过开始 N 秒统计 | 5 或 10 | 跳过慢启动阶段 |
-n | 传输指定数据量 | 100M / 1G | 与-t不可同时使用 |
-J | JSON 输出 | 无 | 自动化解析必备 |
--cport | 客户端源端口 | 5201+ | 多实例测试时避免冲突 |
-A | CPU 亲和性 | 0/1/2 | 多核负载分担 |
这张表不是全部参数,但覆盖了我在车载测试中用到的绝大多数场景。对于刚上手的人来说,先熟练掌握-s、-c、-u、-b、-t、-J这几个就够了,其他参数按需查阅即可。
7. 写在最后的一点切身体会
回到一开始的问题:iperf3 到底难不难用?我的答案是:命令本身 10 分钟就能学会,难的是如何设计测试、如何解读结果。同一台设备,单线程和 8 线程的吞吐可以差出好几倍;同一个速率,UDP 和 TCP 的表现可能完全不同。作为测试工程师,你手里拿到的不仅仅是一个测速工具,而是一面能照出网络系统内部问题的镜子。
我个人的习惯是每次测试前先写下三个问题的预判:这条链路的理论瓶颈在哪里?中间有哪些设备可能影响结果?测试结果的差异是否真实反映了业务劣化,还是测试方法本身引入的误差?带着这些问题去跑 iperf3,每次都能有收获。哪怕只是观察重传率的变化,也比单纯拉一条带宽曲线更有价值。
最后分享一个我踩过好几回的坑:在产线自动化测试中,千万不要漏掉每次测试前的环境复位。有些 iperf3 服务端进程会残留上一条连接的 socket 状态,如果你在脚本里不加-O也不手动清理,第二轮的慢启动统计会把平均带宽拉低 20% 以上。我的做法是每次测试前用pkill -9 iperf3,再启动新的服务端实例。这个细节虽然不起眼,却往往决定了你测得的数据能不能真实反映产线设备的质量。