linux下丢包率需通过/proc/net/dev或/sys/class/net/xxx/statistics中增量计数(如rx_dropped、rx_overrun)与rx_packets差值计算得出,非直接提供;采样间隔≥1秒,须防除零、回绕与抖动。

Linux 下用 /proc/net/dev 解析网卡收发包统计,但丢包率不直接提供
Linux 内核不直接暴露「丢包率」或「错误率」的实时百分比,/proc/net/dev 只提供累计计数:接收/发送的总包数、错误数、丢弃数、队列溢出数等。你需要自己做差值计算才能得到「近期丢包率」。
关键字段(以第一行为例):ens33: 123456789 12345 0 0 0 0 0 0 987654321 98765 0 0 0 0 0 0,其中第3列为接收错误数(rx_errors),第4列为接收丢弃数(rx_dropped),第5列为接收溢出数(rx_overrun);第11列为发送错误数(tx_errors)。
- 丢包率 ≈
(rx_dropped + rx_overrun)/rx_packets(需两次采样取 delta,否则初始值为0时除零) - 错误率 ≈
rx_errors/rx_packets(同样必须用增量,非累计比) - 采样间隔建议 ≥ 1 秒,太短会导致分母为0或抖动剧烈
- 注意:某些驱动将丢包计入
rx_dropped,有些则归入rx_overrun或rx_frame_errors(后者在/sys/class/net/xxx/statistics/下)
Linux 下读取 /sys/class/net/xxx/statistics/ 获取更细粒度指标
/sys/class/net/ 下每个网卡目录的 statistics/ 子目录提供更细分的硬件/驱动级计数器,比如 rx_frame_errors、rx_crc_errors、tx_aborted_errors,比 /proc/net/dev 更适合定位错误类型。
示例路径:/sys/class/net/ens33/statistics/rx_errors,该文件只含一个整数,可直接 std::ifstream 读取:
std::ifstream f("/sys/class/net/ens33/statistics/rx_errors");
unsigned long val;
f >> val;
- 不是所有网卡都支持全部字段,缺失时读取会失败(
failbit置位),需容错处理 -
rx_dropped在此路径下也存在,但语义可能与/proc/net/dev不完全一致(例如是否包含防火墙 DROP) - 该路径下数值是只读、无锁、原子更新的,比解析文本文件更轻量
Windows 下用 GetIfEntry2() 和 GetIfTable2() 替代已废弃的 GetIfTable()
Windows 从 Vista 起推荐使用 GetIfEntry2()(单接口)或 GetIfTable2()(全表),它们返回 MIB_IF_ROW2 结构体,字段如 InDiscards、InErrors、OutErrors、OutQLen 直接对应 RFC2863 定义的 IF-MIB。
注意点:
- 必须链接
Iphlpapi.lib,且调用前需#include <iphlpapi.h></iphlpapi.h>和#pragma comment(lib, "iphlpapi.lib") -
GetIfEntry2()需要先用ConvertInterfaceAliasToLuid()或GetIfTable2()查 LUID,不能直接用适配器名称字符串 - 返回的计数器是 64 位无符号整数(
ULONG64),避免用int截断 - 部分虚拟网卡(如 Hyper-V vSwitch、WSL2 虚拟网卡)可能报告 0 或不更新某些字段,需实测验证
C++ 实现跨平台差值采集时,最易忽略的三个坑
丢包率不是静态值,本质是「单位时间内的变化率」,所有跨平台实现都绕不开差值逻辑。但多数人栽在细节上:
- 没做防抖:第一次采样后立刻计算,导致分母为0或分子突变 → 必须缓存上一次值,且仅当两次采样间隔 ≥ 500ms 才参与计算
- 没处理回绕:某些网卡计数器是 32 位无符号整型,满值后归零(如老千兆网卡的
rx_packets),直接相减会得到巨大负数 → 应用if (now 类似的回绕检测 - 混用指标来源:比如用
/proc/net/dev的rx_dropped除以/sys/class/net/xxx/statistics/rx_packets,二者统计口径可能不同(前者含协议栈丢弃,后者仅驱动层)→ 同一采集周期内,所有字段必须来自同一数据源
真实环境中,物理网卡丢包率持续 > 0.1% 就值得排查链路或驱动;而虚拟网卡(如 Docker bridge、veth pair)的 tx_dropped 偶尔跳变属正常,重点看是否持续增长。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











