# 如何用Linux C++编程监听网络事件
在 Linux C++ 程序里,要检测 网络恢复 或 网络变化,常见有几种方法,取决于你是想检测物理链路变化(网卡 up/down)、IP/路由变化,还是真正的网络可达性变化。
# 1. 使用 netlink 监听内核的网络事件(推荐)
Linux 提供了 netlink
(尤其是 RTNETLINK
)机制,可以订阅网络接口、IP 地址、路由表等变化事件,而不需要轮询。
优点:实时、无需 root、系统级事件源。
核心步骤:
- 创建
NETLINK_ROUTE
类型的 netlink socket。 - 订阅
RTMGRP_LINK
(链路事件)、RTMGRP_IPV4_IFADDR
(IPv4 地址变化)、RTMGRP_IPV6_IFADDR
等多播组。 - 解析
struct nlmsghdr
中的消息,判断接口 up/down、IP 改变等。
示例代码(简化版):
#include <iostream>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
#include <cstring>
int main() {
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (fd < 0) {
perror("socket");
return 1;
}
sockaddr_nl addr{};
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("bind");
close(fd);
return 1;
}
char buf[4096];
while (true) {
int len = recv(fd, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv");
continue;
}
for (nlmsghdr* nh = (nlmsghdr*)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
if (nh->nlmsg_type == NLMSG_DONE) break;
if (nh->nlmsg_type == RTM_NEWADDR) {
std::cout << "IP 地址变化\n";
} else if (nh->nlmsg_type == RTM_DELADDR) {
std::cout << "IP 地址删除\n";
} else if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK) {
std::cout << "网络接口变化(up/down)\n";
}
}
}
close(fd);
return 0;
}
这种方式可以精准地捕捉“网线拔插”“Wi-Fi 连接/断开”“IP 更新”等。
# 2. 使用 libnl 库(netlink 的封装)
libnl
封装了 netlink 通信,更易用。
sudo apt install libnl-3-dev libnl-genl-3-dev
用法类似,但解析消息更方便。
# 3. 使用 NetworkManager D-Bus API
如果你的系统用 NetworkManager 管理网络,可以通过 D-Bus 监听网络状态变化:
/org/freedesktop/NetworkManager
的PropertiesChanged
信号会通知网络变化。- 可以判断
Connectivity
或ActiveConnection
状态。
适合桌面环境或依赖 NetworkManager 的系统,但不适用于嵌入式(可能没装 NM)。
# 4. 检测真正的网络可用性
上面的方法只能告诉你链路或配置变了,但不保证“能访问互联网”。 如果需要检测网络是否恢复,可以定时或在事件触发时做一次 ping 或 TCP 连接测试:
system("ping -c 1 8.8.8.8 > /dev/null 2>&1");
或用 C++ socket 尝试连接一个已知可靠的服务器(如 DNS 53 端口)。
✅ 总结推荐方案:
- 底层实时检测:用 netlink (RTNETLINK) 监听接口/IP/路由变化。
- 需要跨发行版统一接口:用 NetworkManager D-Bus API。
- 需要确认互联网可达:结合 netlink 事件 + ping/连接测试。