要在Linux中以编程方式检测IP地址更改,您可以使用以下方法:
netlink
套接字接收路由消息。#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include <unistd.h>
#include<linux/netlink.h>
#include<linux/rtnetlink.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main() {
int sock;
struct sockaddr_nl local;
struct msghdr msg;
struct iovec iov;
struct nlmsghdr *nlh;
char buffer[4096];
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock < 0) {
perror("socket");
return 1;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
if (bind(sock, (struct sockaddr *)&local, sizeof(local)) < 0) {
perror("bind");
return 1;
}
memset(&msg, 0, sizeof(msg));
iov.iov_base = buffer;
iov.iov_len = sizeof(buffer);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
while (1) {
int len;
len = recvmsg(sock, &msg, 0);
if (len < 0) {
perror("recvmsg");
return 1;
}
nlh = (struct nlmsghdr *)buffer;
while (NLMSG_OK(nlh, len)) {
if (nlh->nlmsg_type == NLMSG_DONE) {
break;
}
if (nlh->nlmsg_type == RTM_NEWADDR || nlh->nlmsg_type == RTM_DELADDR) {
struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
struct rtattr *rta = IFA_RTA(ifa);
int rtasize = IFA_PAYLOAD(nlh);
while (RTA_OK(rta, rtasize)) {
if (rta->rta_type == IFA_LOCAL || rta->rta_type == IFA_ADDRESS) {
char addr[INET6_ADDRSTRLEN];
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)RTA_DATA(rta);
inet_ntop(AF_INET6, &sin6->sin6_addr, addr, sizeof(addr));
printf("IP address %s on interface %d\n", addr, ifa->ifa_index);
}
rta = RTA_NEXT(rta, rtasize);
}
}
nlh = NLMSG_NEXT(nlh, len);
}
}
close(sock);
return 0;
}
ioctl
套接字获取网络设备信息。#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
int main() {
int sock;
struct ifreq ifr;
struct sockaddr_in *sin;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
return 1;
}
for (int i = 0; i < 10; i++) {
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth%d", i);
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
continue;
}
sin = (struct sockaddr_in *)&ifr.ifr_addr;
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &sin->sin_addr, addr, sizeof(addr));
printf("IP address %s on interface %s\n", addr, ifr.ifr_name);
}
close(sock);
return 0;
}
这两种方法都可以用于检测Linux系统中IP地址的更改。第一种方法使用netlink
套接字接收路由消息,可以检测到IPv4和IPv6地址的更改。第二种方法使用ioctl
套接字获取网络设备信息,只能检测到IPv4地址的更改。
领取专属 10元无门槛券
手把手带您无忧上云