Linux下直接读取/proc/net/dev获取网卡流量最轻量可靠,需跳过前两行表头,提取每行冒号后第1和第9个字段(rx_bytes、tx_bytes),用std::stoull转为uint64_t,两次采样求差值除以时间间隔得速率。

Linux 下直接读 /proc/net/dev 是最轻量、最可靠的方式;Windows 需用 GetIfTable2 或 GetIfEntry2,别碰 GetIfTable(已废弃且精度差)。
Linux:解析 /proc/net/dev 获取实时流量
这个文件每秒更新,内核保证原子性,无需 root 权限,也没有竞态风险。关键不是“怎么读”,而是“怎么解析”和“怎么避免误算”。
- 跳过前两行(标题行),每行格式为:
iface: rx_bytes rx_packets ... tx_bytes tx_packets ...,注意冒号后有多个空格或制表符,不能简单std::istringstream按空格切分 - 接口名含冒号(如
eth0:),需先去掉末尾冒号再 trim,否则匹配失败 - 数值是无符号 64 位整数,必须用
std::stoull或strtoull解析,用int或long会溢出(千兆网满速 1 秒就超 2GB) - 两次采样间隔建议 ≥ 100ms,太短会导致
rx_bytes变化不明显,除法结果为 0
示例片段(仅核心逻辑):
std::ifstream dev{"/proc/net/dev"};
std::string line;
while (std::getline(dev, line)) {
if (line.find(':') == std::string::npos) continue;
auto pos = line.find(':');
std::string iface = line.substr(0, pos);
boost::trim(iface); // 或手写 trim
if (iface != "eth0") continue; // 替换为目标接口
std::vector<:string> fields = split_by_any_of(line.substr(pos+1), " \t");
uint64_t rx_bytes = std::stoull(fields[0]);
uint64_t tx_bytes = std::stoull(fields[8]);
}
</:string>
Windows:用 GetIfTable2 替代老旧 API
GetIfTable 返回的 MIB_IFROW 中 dwInOctets/dwOutOctets 是 32 位,10G 网卡几秒就回绕;GetIfTable2 返回的 IF_ROW2 含 InOctets 和 OutOctets 字段,均为 UINT64,且支持按名称精确查询(不用遍历所有接口)。
- 必须链接
iphlpapi.lib,头文件包含和 - 调用前检查 OS 版本:低于 Windows 7 SP1 不支持
GetIfTable2,需降级到GetIfTable2Ex(但后者只在 Win10+ 完整支持) -
GetIfEntry2比GetIfTable2更高效——如果你只监控单个接口,用它传入LUID(可通过ConvertInterfaceAliasToLuid从接口名获取),避免全表拷贝 - 注意
IF_ROW2::OperStatus,值为IfOperStatusUp才代表接口真正 up,否则流量可能为 0 或陈旧
跨平台封装要注意的三个细节
别以为把两个平台逻辑塞进 #ifdef 就完事了。真实项目里,这些点最容易引发隐性 bug:
- Linux 的
/proc/net/dev统计的是**驱动层收发字节数**,包含错误帧、FCS 校验失败包;Windows 的InOctets/OutOctets是协议栈入口/出口字节数,不含底层丢弃包——两者语义不等价,混用做对比会偏差 5%~10% - 时间戳必须用单调时钟:Linux 用
clock_gettime(CLOCK_MONOTONIC, &ts),Windows 用QueryPerformanceCounter;用time()或GetSystemTimeAsFileTime会导致速率计算抖动 - 接口名映射不可硬编码:Linux 可能是
enp0s3、ens33,Windows 是以太网或Ethernet 2;应提供运行时配置项或自动探测(如匹配is_ether+OperStatusUp)
实际部署时,最大的坑不是读不准,而是没意识到:同一块物理网卡启用多队列(RSS)或 DPDK 后,/proc/net/dev 仍只显示总和,而用户态抓包工具看到的可能是某个队列的局部数据——这时候你得确认监控目标到底是“内核协议栈视角”还是“硬件收发视角”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











