Linux下C++需通过/proc/net/dev或ethtool ioctl获取网卡丢包/错误率,二者均只提供累计值,须两次采样做差计算比率;/proc/net/dev轻量无需root,但仅含基础统计;ethtool可获硬件级错误但需cap_net_admin权限。

Linux 系统下 C++ 无法直接通过标准库或 POSIX 接口获取网络适配器的丢包率、错误率;必须读取 /proc/net/dev 或调用 ethtool 底层 ioctl,且丢包率需自行计算(无现成“百分比”字段)。
读取 /proc/net/dev 获取原始收发统计
这是最轻量、无需 root 权限的方式,但只提供累计计数(如 rx_errors、tx_dropped),不包含速率或百分比。你需要两次采样后做差值计算:
- 每行格式为:
Inter-| Receive | Transmit,实际数据行以接口名开头(如eth0:),注意冒号和对齐空格 - 第 2 列是
rx_bytes,第 3 列是rx_packets,第 4 列是rx_errors,第 5 列是rx_dropped;发送侧对应第 10–13 列 - 字段顺序在不同内核版本中稳定,但列宽可能变化,建议用空格分割 + 跳过空字符串,而非固定列索引
- 示例解析逻辑:
std::ifstream dev("/proc/net/dev"); std::string line; while (std::getline(dev, line)) { if (line.find(":") != std::string::npos && line.find("lo:") == std::string::npos) { std::istringstream iss(line.substr(line.find(':') + 1)); std::vector<unsigned long> fields; for (std::string val; iss >> val; ) { fields.push_back(std::stoull(val)); } // fields[2] = rx_packets, fields[3] = rx_errors, fields[4] = rx_dropped... } }</unsigned>
用 ioctl(SIOCETHTOOL) 获取更细粒度硬件计数器
当需要网卡驱动暴露的底层错误(如 CRC 错误、overrun、fifo errors),/proc/net/dev 不够用,必须走 ethtool 接口。这要求:
- 打开接口对应的 socket(
socket(AF_INET, SOCK_DGRAM, 0)),非文件读取 - 构造
struct ethtool_stats,先调用ETHTOOL_GSSET_INFO查可用统计项数量,再分配足够 buffer 调用ETHTOOL_GSTATS - 返回的数值是驱动定义的,不同厂商命名差异大(如
rx_crc_errors、rx_missed_errors),需结合ethtool -S eth0手动对照 - 普通用户默认无权限执行该 ioctl,需
cap_net_admincapability 或 root;生产环境建议用 systemd service 加 capability,而非直接跑 root 进程
丢包率/错误率不能直接读,必须时间窗口内差值计算
所有内核接口只提供单调递增的累计值,所谓“率”必须由应用层实现时间差分:
- 丢包率 ≈
(current_rx_dropped - last_rx_dropped) / (current_rx_packets - last_rx_packets)(仅适用于接收端,且分母需 > 0) - 错误率同理,但
rx_errors包含可恢复错误(如帧校验失败但未丢包),与业务感知的“失败”不等价 - 采样间隔太短(30s)则失去监控灵敏度;推荐 2–5 秒,并缓存至少两个历史点
- 注意溢出:
unsigned long long在高流量网卡上可能数小时就翻转,需检测回绕(当前值
别忽略 /sys/class/net//statistics/ 这个替代路径
较新内核(≥3.10)将每个计数器暴露为独立文件(如 /sys/class/net/eth0/statistics/rx_dropped),语义清晰、无需解析文本:
- 路径稳定,权限同
/proc/net/dev(一般用户可读) - 每个文件只含一个数字,
std::stoull(std::string{buf})即可,比正则或空格切分更可靠 - 但部分老旧驱动或虚拟网卡(如 veth、docker0)可能缺失某些字段,需 fallback 到
/proc/net/dev - 注意:该目录下文件是软链接,指向
/sys/devices/.../net/eth0/statistics/...,不要硬编码设备路径
真正难的不是读哪个文件,而是理解哪些字段反映你关心的问题——比如 tx_aborted_errors 在某些网卡上恒为 0,而真实重传由 TCP 层处理;又比如 rx_length_errors 可能被归入 rx_errors 但不计入 rx_dropped。务必用真实流量压测验证字段含义,而不是只看文档。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











