应分别采用windows的pdh api或getiftable2、linux的/proc/net/dev解析或netlink socket,并通过跨平台封装统一接口。windows优先用getiftable2获取mib-ii字段,linux优先用netlink获取rtnl_link_stats64,均需差分计算增量且避免硬编码适配器名。

如果您需要在C++程序中获取系统当前网络适配器的实时错误与丢包统计信息,则需通过操作系统提供的网络接口查询底层驱动暴露的计数器。以下是适用于Windows和Linux平台的多种实现方法:
一、Windows平台:使用PDH性能计数器API
Windows提供PDH(Performance Data Helper)库,可直接读取网络适配器的内置性能计数器,包括“Bytes Received/sec”、“Packets Outbound Errors”、“Packets Received Discarded”等指标,数据精度高且无需管理员权限即可访问部分计数器。
1、调用PdhOpenQuery创建性能查询句柄。
2、使用PdhAddCounter添加目标计数器路径,例如\Network Interface(<i>适配器名称</i>)\Packets Outbound Errors和\Network Interface(<i>适配器名称</i>)\Packets Received Discarded。
3、调用PdhCollectQueryData触发一次数据采集。
4、通过PdhGetFormattedCounterValue获取PDH_FMT_LONG格式的整数值。
5、循环调用步骤3–4,间隔1秒以上以获得稳定差分值。
6、注意:适配器名称需通过GetAdaptersInfo或GetAdaptersAddresses动态枚举,不可硬编码为“以太网”或“Wi-Fi”等中文名,应使用GetIfTable2返回的LUID对应别名。
二、Windows平台:调用GetIfEntry2与GetIfTable2 API
Windows 8/Server 2012及以上系统支持GetIfEntry2和GetIfTable2函数,可直接从内核网络栈获取每个适配器的ifInErrors、ifOutErrors、ifInDiscards、ifOutDiscards等标准MIB-II字段,该方式不依赖性能库,响应更快且无计数器路径解析开销。
1、调用GetIfTable2获取所有适配器的PMIB_IF_TABLE2结构体数组。
2、遍历数组,通过InterfaceLuid匹配目标适配器(如主活动接口),或依据OperStatus == IfOperStatusUp筛选启用状态。
3、提取dwInErrors、dwOutErrors、dwInDiscards、dwOutDiscards字段值。
4、两次调用间隔至少500毫秒,计算差值即得周期内错误/丢包增量。
5、必须链接Iphlpapi.lib并定义_WIN32_WINNT >= 0x0602。
三、Linux平台:解析/proc/net/dev文件
Linux内核通过/proc/net/dev虚拟文件暴露每个网络设备的收发统计,其中第2列(receive packets)、第3列(receive errors)、第4列(receive drop)、第10列(transmit packets)、第11列(transmit errors)、第12列(transmit drop)分别对应关键指标,文本解析轻量高效,适用于嵌入式及服务端监控场景。
1、以只读方式打开/proc/net/dev文件。
2、跳过前两行表头,逐行读取设备行,按空白符分割字段。
3、定位目标接口行(如eth0或wlan0),提取第2、3、4、10、11、12个字段(索引从0起)。
4、将各字段字符串转换为unsigned long long类型。
5、缓存上一次读取值,与本次做减法得到实时增量。
6、注意字段顺序固定但空格数量不一,须用strtok_r或std::istringstream跳过多余空白。
四、Linux平台:使用netlink socket查询RTNL_LINK消息
通过AF_NETLINK套接字发送RTM_GETLINK请求,接收内核返回的struct ifinfomsg及附带的IFLA_STATS64属性,可获取64位精度的错误与丢包计数,该方式避免了/proc文件系统解析开销,且能监听接口状态变更事件,适合长期驻留的监控进程。
1、调用socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)创建netlink套接字。
2、绑定本地地址,设置nl_pid为当前进程PID,nl_groups为0。
3、构造struct nlmsghdr,设置nlmsg_type = RTM_GETLINK,nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP。
4、发送消息后循环调用recv接收响应,解析每个struct ifinfomsg及其RTA_STATS64属性。
5、从struct rtnl_link_stats64中提取rx_errors、tx_errors、rx_dropped、tx_dropped成员。
6、需包含
五、跨平台封装建议:基于条件编译的统一接口
为简化多平台维护,可定义统一结构体NetAdapterStats,包含rx_errors、tx_errors、rx_dropped、tx_dropped字段,并在编译期根据_WIN32或__linux__宏选择具体实现分支,对外暴露bool GetAdapterStats(const char* name, NetAdapterStats* out)接口。
1、Windows分支优先尝试GetIfTable2,失败则回落至PDH。
2、Linux分支优先使用netlink,若权限不足或失败则自动切换至/proc/net/dev解析。
3、接口参数name为空时默认选取第一个OperStatusUp(Windows)或flags & IFF_UP(Linux)的非loopback接口。
4、所有实现均应在单次调用中完成完整采集,禁止在函数内部启动后台线程或依赖全局状态机。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











