/proc/net/dev是linux下获取网卡收发字节数最轻量可靠的方式,解析时取每行第2、10列的rx_bytes和tx_bytes,用std::stoull转换,两次采样差值除以间隔得b/s速率。

Linux下用/proc/net/dev读取网卡收发字节数最简单
直接读取 /proc/net/dev 是获取实时网络速率最轻量、最可靠的方式。它不依赖第三方库,无权限问题,且内核保证数据一致性。每秒读一次,两次差值除以时间间隔就能算出B/s速率。
- 第一行和第二行是标题,真实数据从第三行开始;每行格式为
interface: rx_bytes rx_packets ... tx_bytes tx_packets ... - 注意字段对齐:不同内核版本字段数可能不同,
rx_bytes和tx_bytes始终在第2和第10列(空格分隔后) - 示例解析:读到
eth0: 123456789 ... 987654321,前数是接收字节数,后数是发送字节数 - 别用
std::stoi直接转大数值——可能溢出,改用std::stoull或strtoull
Windows上用GetIfEntry2获取每秒速率需两次采样
Windows没有类似 /proc 的伪文件系统,必须调用 GetIfEntry2(推荐)或旧版 GetIfEntry。它返回的是累计字节数,要算速率就得至少两次调用,间隔1秒以上。
将提醒同步至 Windows/Outlook 日历。用户提及「提醒我」「设置提醒」「加到日历」「同步到日历」「日程」「calendar」「日历」时触发。支持Microsoft Graph API 设备代码流认证,无需 Web 服务器,直接写入用户 Outlook 日历。
- 必须用
InitializeCriticalSection或std::mutex保护共享的上次采样值,否则多线程下结果错乱 -
GetIfEntry2返回结构体中ifInOctets和ifOutOctets是 uint64_t 类型,对应接收/发送总字节数 - 若设备名是
L"Ethernet",但GetIfEntry2用的是 LUID,得先用ConvertInterfaceAliasToLuid转换 - 采样间隔太短(如100ms)会导致浮点误差放大,建议固定用1000ms,避免用
QueryPerformanceCounter自己算间隔
跨平台封装时别硬编码字段索引或结构体偏移
Linux字段顺序、Windows结构体字段名和大小都随系统版本变,硬写索引或 offsetof 容易崩溃。应封装成两个独立实现,通过编译宏隔离。
- 用
#ifdef _WIN32/#else分开实现,不要试图“统一接口”后塞进一个函数里 - Linux侧解析
/proc/net/dev时,用std::istringstream+std::ws跳过空白,再循环getline比正则更稳 - Windows侧每次调用
GetIfEntry2前必须检查返回值是否为NO_ERROR,失败时跳过本次计算,不强行用旧值 - 速率单位统一输出为
doubleB/s,上层自行转 K/s 或 Mbps,避免在底层做除法引入浮点误差
实时性要求高时注意采样频率与精度权衡
所谓“实时”不是越快越好。频繁读取 /proc/net/dev 或反复调用 GetIfEntry2 会增加系统调用开销,且网络计数器本身更新就有延迟(通常几十ms级)。
- 普通监控场景用1s间隔足够;UI刷新可插值平滑,不必每帧都重算
- Linux下若需更高精度,可用
netlinksocket 订阅NETLINK_ROUTE的RTM_NEWLINK事件,但仅反映接口启停,不提供字节计数 - Windows没有等价机制,
GetIfEntry2是唯一稳定方案;试图用 WMI(Win32_PerfFormattedData_Tcpip_NetworkInterface)延迟更大,且默认禁用性能计数器 - 别忽略单位:网卡驱动上报的字节数包含帧头(如Ethernet header),和应用层payload不等,这点在做协议分析时容易误判
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










