linux 通过读取 /proc/net/dev 获取网卡收发字节数并差值计算带宽,windows 则需调用 getiftable2;两者均须两次采样求差、除以时间间隔,注意接口识别、单位换算(b/s→mbps×8)、数据类型(uint64_t)及权限问题。

Linux 下读取 /proc/net/dev 是最直接可靠的方式
Linux 内核通过 /proc/net/dev 暴露各网络接口的收发字节数,这是获取带宽使用率的底层事实来源。它不依赖守护进程或额外权限,只要能读文件就能用。
关键点在于:该文件每秒更新,两次采样做差值再除以时间间隔,才能得到实时带宽(单位通常是 B/s)。别直接读一次就当“当前带宽”——那只是累计值。
-
std::ifstream打开/proc/net/dev,跳过前两行(标题和分隔线) - 按行解析,每行格式为
interface: rx_bytes rx_packets ... tx_bytes tx_packets ...,注意冒号后有空格,interface名可能含:(如lo:) - 提取第 2 列(
rx_bytes)和第 10 列(tx_bytes),用std::stoull转换;别用atoi,会溢出 - 建议固定采样间隔(如 1 秒),用
std::this_thread::sleep_for控制,避免轮询浪费 CPU
Windows 上必须用 GetIfTable2 或 GetIfEntry2
Windows 没有类 Unix 的 procfs,不能靠读文件。WMI 太慢、PowerShell 调用太重,真正低开销的方式是调用 IP Helper API 的 GetIfTable2(推荐)或 GetIfEntry2。
这两个函数返回结构体数组,其中 ifInOctets 和 ifOutOctets 字段就是对应接口的接收/发送总字节数。和 Linux 一样,需两次调用取差值。
- 链接
Iphlpapi.lib,包含<iphlpapi.h></iphlpapi.h>和<winsock2.h></winsock2.h> -
GetIfTable2返回的是PMIB_IF_TABLE2,遍历Table[i].InterfaceLuid和Table[i].Alias匹配目标网卡(如"Ethernet") - 注意:
GetIfTable2在 Windows 7 及以下不可用,若需兼容旧系统,降级用GetIfTable(但只支持 IPv4 且字段精度低) - 调用失败时检查
GetLastError(),常见错误码包括ERROR_NOT_SUPPORTED(系统太老)、ERROR_ACCESS_DENIED(UAC 提权未满足)
跨平台封装要注意接口名匹配和采样时机
写一个跨平台函数时,最大的坑不是 API 差异,而是“哪个接口算‘当前网络’”。用户说的“当前网络”往往指默认路由出口(如 Wi-Fi 或以太网),而不是 lo 或 veth 容器接口。
Linux 下可通过 ip route | grep '^default' | awk '{print $5}' 获取默认出口名;Windows 下需查 MIB_IF_TABLE2 中 Table[i].OperStatus == IF_OPER_STATUS_UP 且 Table[i].ConnectionType == IF_CONNECTION_DEDICATED 的活跃物理接口。
- 不要硬编码接口名(如
"eth0"),不同发行版命名规则不同(ens33、enp0s3、net0) - 两次采样之间务必 sleep 稳定间隔,否则计算出的带宽抖动极大;用
std::chrono::steady_clock计时,别用system_clock(受系统时间调整影响) - 如果目标是监控而非实时显示,建议采样间隔 ≥ 2 秒——短于 1 秒的差值噪声大,且
/proc/net/dev和GetIfTable2本身更新频率也有下限
别把字节数当带宽,单位换算和方向混淆是高频错误
拿到 rx_bytes 和 tx_bytes 差值后,直接输出数字毫无意义。常见错误包括:忘记除以时间、误把 B/s 当 Mbps、把收发混成一个值。
- 1 B/s = 8 b/s,但网络设备厂商标称带宽(如 “100 Mbps”)是 bit/s,而系统统计全是 byte/s;转换时乘 8 还是除 8 必须理清
- 上传(TX)和下载(RX)应分开显示;合起来叫“总带宽”容易误导——TCP ACK 包小但频繁,RX/TX 不对称是常态
- 示例:两次采样得 RX 差值为 1250000 B,间隔 1.02 秒 → 实际下载 ≈ 1225490 B/s ≈ 9.8 Mbps(注意保留一位小数,原始数据没那么准)
- 别用
float存字节数差值——64 位计数器差值可能超 2³²,必须用uint64_t
实际部署时,最常被忽略的是权限和采样稳定性:Linux 下容器里可能挂载了精简的 /proc,看不到完整 /proc/net/dev;Windows 服务模式运行时若没设 INTERACTIVE 权限,GetIfTable2 会静默失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











