应直接用 ethtool(linux)或 getifentry2(windows)获取物理链路协商速率:ethtool eth0 提取 speed 字段得真实 mbps 值;getifentry2 通过 luid 获取 transmitlinkspeed(bps),需 uint64 接收并转 mbps,operstatus 非活动时无效。

直接查硬件协商结果,别算流量、别读/sys/class/net/*/speed——它不可靠,常返回0或Unknown!。
Linux 下用 ethtool 读真实链路速率
物理速率不是“当前用了多少”,而是网卡和交换机协商出来的固定能力值。ethtool 通过 ioctl 直通内核驱动,拿到的是 Link settings 里的原始字段。
-
ethtool eth0 | grep -i speed输出类似Speed: 1000Mb/s,这才是你要的 1Gbps - 脚本提取建议:
ethtool eth0 2>/dev/null | awk '/Speed:/ {gsub(/[^0-9]/, "", $2); print $2}'(自动去单位、容错空格) - 非 root 用户可能被驱动限制(如 Mellanox、某些 Realtek 厂商驱动),
Permission denied时必须提权 - 虚拟网卡(
veth、docker0、br-前缀)返回Unknown!是正常行为,不代表失败
Windows 下必须用 GetIfEntry2,别碰 GetIfEntry
GetIfEntry 的 dwSpeed 字段在 Vista 后已失效,千兆以上网卡大概率返回 0 或错误值。真正可用的是 GetIfEntry2,它返回 IF_ENTRY_TABLE2 结构体。
-
TransmitLinkSpeed和ReceiveLinkSpeed是uint64_t,单位是 bps;用DWORD或ULONG接收会高位截断(万兆卡显示为 0) - 若
OperStatus == IF_OPER_STATUS_NON_OPERATIONAL,说明链路未激活,此时TransmitLinkSpeed无效,不应当作 0 使用 - 调用前需用
ConvertInterfaceAliasToLuid或GetIfTable2先查出目标接口的LUID,再传给GetIfEntry2
别用 WMI 的 Win32_NetworkAdapterConfiguration.Speed
这个字段实际对应的是 MaxSpeed,但很多驱动不填、WMI 层也不强制刷新,实测 Windows 10/11 上大量网卡返回 NULL 或旧值(比如插着 2.5G 网线却报 1000000000)。
- 它不反映实时协商结果,只反映驱动上报的“理论最大值”
- 需要 COM 初始化、WbemLocator、权限提升,开销大且不稳定
- 若真要用 WMI,优先查
Win32_PerfFormattedData_Tcpip_NetworkInterface的CurrentBandwidth(单位 bps),但它其实是估算值,非链路协商值
跨平台代码里最容易漏掉的兼容点
同一个程序在 Linux 和 Windows 上跑,最常崩在两处:接口名映射和权限兜底。
- Linux 接口名(
eth0、enp0s31f6)和 Windows 接口名(以太网、Ethernet 2)无法直通,必须用索引或 LUID 对齐 - Linux 下
ethtool调用失败时,不要 fallback 到/sys/class/net/*/speed——它比不返回还危险(常缓存旧值) - Windows 下
GetIfEntry2失败后,也别 fallback 到GetIfEntry,它已经废弃,且行为不可控 - 所有链路速率值,建议统一转成 Mbps 整数并缓存 1–2 秒,避免高频重复调用驱动接口
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











