Linux下丢包率需自行计算:两次采样/proc/net/dev中rx_dropped、tx_dropped与rx_packets、tx_packets的差值比,分母取总包数差并防零,间隔1–5秒以平衡实时性与稳定性。

Linux 下用 /proc/net/dev 解析网卡收发包统计,但丢包率不直接提供
Linux 内核不暴露“实时丢包率”这个指标——它只记录累计丢包数(rx_dropped、tx_dropped)、错误数(rx_errors、tx_errors)和总收发包数。所谓“丢包率”,必须你自己在两个时间点采样后计算:(current_dropped - last_dropped) / (current_packets - last_packets)。注意分母不能为 0,且建议用 rx_packets + tx_packets 作总基数更合理(单看 rx 或 tx 容易失真)。
常见错误是直接读一次 /proc/net/dev 就输出“丢包率 0.02%”,这毫无意义;也有人误把 rx_dropped 当成瞬时值,其实它是驱动层累计计数,重启网卡或内核模块才会清零。
- 每次读取需跳过前两行(头部注释),按空格/制表符分割,第 2 列是
rx_bytes,第 3 列rx_packets,第 4 列rx_errors,第 5 列rx_dropped,第 10 列tx_packets,第 11 列tx_errors,第 12 列tx_dropped - 推荐用
std::ifstream逐行读,配合std::istringstream拆字段,避免sscanf对齐失败 - 接口名(如
eth0)出现在每行开头,注意前后可能有空格或冒号,std::string::find后用substr提取更稳
Windows 上调用 GetIfEntry2() 获取 NIC 统计,但需注意权限与兼容性
GetIfEntry2() 是 Windows 8.1+ 推荐的 API,能拿到 InErrors、InDiscards、OutErrors、OutDiscards 等字段,对应 RFC 2863 定义的丢弃/错误计数。但它要求进程启用 SeNetworkConfigurationPrivilege 权限(通常管理员运行即可),否则返回 ERROR_ACCESS_DENIED。
容易被忽略的是:这些值仍是累计值,不是速率;且不同网卡驱动对“discard”的定义不一致——有些把 TCP 校验失败归入 InErrors,有些归入 InDiscards,无法跨厂商横向对比。
立即学习“C++免费学习笔记(深入)”;
- 先用
GetIfTable2()获取所有接口索引(LUID),再对目标接口调GetIfEntry2() - 不要硬编码索引号,接口重启后
Luid可能变,应通过Alias或Description字段匹配 - 若需兼容 Win7,只能退回到
GetIfEntry()(仅支持 IPv4,无InDiscards字段)或 WMI 查询Win32_PerfFormattedData_Tcpip_NetworkInterface
C++ 跨平台采样器设计:两次采样间隔至少 1 秒,避免除零和噪声
丢包率本质是速率指标,采样间隔太短(如 100ms)会导致分母过小、结果剧烈抖动;太长(如 30s)又失去“实时”意义。实测 1–5 秒较平衡,尤其在千兆以上链路中,1 秒内收发包常达数万,足够平滑噪声。
关键不是“怎么读数据”,而是“怎么组织两次读取并安全做差”。别用全局变量存上次值——多线程下会冲突;也别每次 new 一个结构体——频繁分配影响监控本身性能。
- 用 RAII 封装采样器,构造时初始化上一次值为 0,首次调用
sample()只存值不计算 - 计算前检查本次与上次的总包数差值是否 > 100(防低流量下分母过小),否则返回
std::nullopt或 -1 - 错误率建议分开上报:
rx_error_rate和tx_error_rate,因为物理层问题(如光纤衰减)常只影响接收端
真实场景中,rx_dropped 高 ≠ 网络问题,可能是内核队列溢出或防火墙丢包
Linux 下 rx_dropped 常见来源有三类:网卡 Ring Buffer 满(ethtool -S eth0 | grep drop 查 rx_missed_errors)、软中断处理不过来(/proc/net/softnet_stat 第一列非 0)、或 iptables/nftables 显式 DROP。单纯看 /proc/net/dev 无法区分。
所以监控系统里如果发现 rx_dropped 持续上升,下一步该查:cat /proc/net/softnet_stat(看第二列 processed 是否远小于第一列)、ethtool -S 输出中的 rx_discards、以及 nft list ruleset 是否有大量 counter 匹配 DROP 规则。
很多团队把 rx_dropped 当成“网络丢包”报警,结果排查半天发现只是服务器负载高,软中断没及时处理——这种误报比漏报更消耗运维精力。


















