如何在Linux中以编程方式检测IP地址更改?

有没有一种方法来检测本地机器上的Linux在编程上使用C + +的IP地址变化?

Solutions Collecting From Web of "如何在Linux中以编程方式检测IP地址更改?"

在C中,获取我使用的当前IP:

int s; struct ifreq ifr = {}; s = socket(PF_INET, SOCK_DGRAM, 0); strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFADDR, &ifr) >= 0) printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); 

将“eth0”替换为您正在查看的界面。 你现在需要做的是轮询一个变化。

在这里你去..这没有投票。

它只侦听RTM_NEWADDR,但是如果你需要,它应该很容易改变来支持RTM_DELADDR

 #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <net/if.h> int main() { struct sockaddr_nl addr; int sock, len; char buffer[4096]; struct nlmsghdr *nlh; if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { perror("couldn't open NETLINK_ROUTE socket"); return 1; } memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_IPV4_IFADDR; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("couldn't bind"); return 1; } nlh = (struct nlmsghdr *)buffer; while ((len = recv(sock, nlh, 4096, 0)) > 0) { while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) { if (nlh->nlmsg_type == RTM_NEWADDR) { struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(nlh); while (rtl && RTA_OK(rth, rtl)) { if (rth->rta_type == IFA_LOCAL) { uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth))); char name[IFNAMSIZ]; if_indextoname(ifa->ifa_index, name); printf("%s is now %d.%d.%d.%d\n", name, (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff, (ipaddr >> 8) & 0xff, ipaddr & 0xff); } rth = RTA_NEXT(rth, rtl); } } nlh = NLMSG_NEXT(nlh, len); } } return 0; } 

这是不容易的。 每个Linux发行版使用不同的地方来存储IP地址等(如果考虑其他UNIX变体,则会有更多的变化)。 例如,你可以使用/sbin/ifconfig来获得接口的IP地址,但是你甚至不能确定你是否可以在这个地方找到它,或者根本不能确定。

另外,假设你有这个可执行文件,你必须建立一个调用它的线程来获得给定时间(比如说5秒)的数据,然后解释输出。 例如,如果你有桥梁等,这可能会有所不同。也就是说,这并不容易。

我想到的一个解决方案是,如果您有机会使用GNOME或其他广泛的KDE发行版,则可以依靠它们提供的信息/信息。 例如,当设备改变时, NetworkManager向DBUS标准总线输出一个信号。 你必须为这些信号实现一个​​监听器。 信息在这里 (现在不工作,所以这里是一个缓存 )。 注意添加新接口时或者其中一个更改IP地址时的不同消息。 这是我现在可以想到的最好的方式。

如果您的用户使用NetworkManager,则可以通过D-Bus轮询NetworkManager.Connection.Active和NetworkManager.IP4Config,以获得更多的确定此信息的交叉分配方式。

如果安装了iproute2,并且你在2.6内核上,

 /sbin/ip monitor 

将本地接口状态和地址输出更改为标准输出。 你的程序可以读取这个。

你也可以使用与iproute2工具相同的低层机制(我认为它是一个netlink套接字)。

ste建议使用ioctl SIOCGIFADDR在技术上是正确的,但不幸的是,对于现代Linux系统来说,单个接口可以有多个地址而不使用子接口(比如eth0:1),就像现在已经过时的ifconfig一样。

你最好的选择是使用glibc 2.3提供的getifaddrs(3): http ://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html

不幸的是,它效率低下(你得到所有接口上的所有地址的链表,并且必须迭代以找到你感兴趣的地址),但是在大多数情况下,你可能不会每分钟检查一次左右,使架空可以忍受。

一种方法是编写一个cron作业,其中包含对一个gethost库函数系列的调用。 如果使用gethostbyname(),则可以比较h_addr_list的返回值。 请参阅man gethostbyname。

如果你想从你的程序中做到这一点,产生一个同样的事情,然后睡一段时间的pthread。

从rtnetlink的手册页:

描述

Rtnetlink允许读取和修改内核的路由表。 它在内核中用于在各个子系统之间进行通信,尽管这里没有记录这种用法,并且用于与用户空间程序的通信。 网络路由,IP地址,链路参数,邻居设置,排队规则,业务类别和分组分类都可以通过NETLINK_ROUTE套接字来控制。 它是基于netlink消息,请参阅netlink(7)了解更多信息。