如何了解C中接口的IP地址?

假设我正在运行一个名为IpAddresses.c的程序。 我希望该程序根据每个接口获取此设备具有的所有IP地址。 就像ifconfig一样。 我怎样才能做到这一点?

我对ioctl了解不多,但我读到它可能会对我有所帮助。

只需使用getifaddrs() 。 这是一个例子:

#include  #include  #include  #include  int main () { struct ifaddrs *ifap, *ifa; struct sockaddr_in *sa; char *addr; getifaddrs (&ifap); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family==AF_INET) { sa = (struct sockaddr_in *) ifa->ifa_addr; addr = inet_ntoa(sa->sin_addr); printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr); } } freeifaddrs(ifap); return 0; } 

这是我在我的机器上得到的输出:

 Interface: lo Address: 127.0.0.1 Interface: eth0 Address: 69.72.234.7 Interface: eth0:1 Address: 10.207.9.3 

这里有一些可能对你有帮助的Linux示例代码。

 #include  #include  #include  #include  #include  #include  #define INT_TO_ADDR(_addr) \ (_addr & 0xFF), \ (_addr >> 8 & 0xFF), \ (_addr >> 16 & 0xFF), \ (_addr >> 24 & 0xFF) int main() { struct ifconf ifc; struct ifreq ifr[10]; int sd, ifc_num, addr, bcast, mask, network, i; /* Create a socket so we can use ioctl on the file * descriptor to retrieve the interface info. */ sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd > 0) { ifc.ifc_len = sizeof(ifr); ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr; if (ioctl(sd, SIOCGIFCONF, &ifc) == 0) { ifc_num = ifc.ifc_len / sizeof(struct ifreq); printf("%d interfaces found\n", ifc_num); for (i = 0; i < ifc_num; ++i) { if (ifr[i].ifr_addr.sa_family != AF_INET) { continue; } /* display the interface name */ printf("%d) interface: %s\n", i+1, ifr[i].ifr_name); /* Retrieve the IP address, broadcast address, and subnet mask. */ if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0) { addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr; printf("%d) address: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(addr)); } if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0) { bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr; printf("%d) broadcast: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(bcast)); } if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0) { mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr; printf("%d) netmask: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(mask)); } /* Compute the current network value from the address and netmask. */ network = addr & mask; printf("%d) network: %d.%d.%d.%d\n", i+1, INT_TO_ADDR(network)); } } close(sd); } return 0; } 

使用getifaddrs()的解决方案很棒。 我建议只改进一个:

 --- chrisaycock +++ normando @@ -11,7 +11,7 @@ getifaddrs (&ifap); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family==AF_INET) { + if (ifa->ifa_addr && ifa->ifa_addr->sa_family==AF_INET) { sa = (struct sockaddr_in *) ifa->ifa_addr; addr = inet_ntoa(sa->sin_addr); printf("Interface: %s\tAddress: %s\n", ifa->ifa_name, addr); 

仅仅因为我自己遇到了分段错误。

请参阅此其他Stack Overflow问题, 枚举分配给网络接口的每个IP地址

总之,您可以使用:

  • ioctl(SIOCGIFCONF) – >传统的ioctl
  • getifaddrs() – >来自BSDi,现在也在Linux和BSD上。
  • RTNETLINK(Linux)

你可以尝试这样的事情:

 struct ifreq ifr[MAX_INTERFACES]; struct ifconf ifc; memset(ifr, 0, sizeof(ifr)); ifc.ifc_len = sizeof(ifr); ifc.ifc_req = ifr; // Get the list of interfaces if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { fprintf(stderr, "ioctl SIOCGIFCONF failed: %d", errno); } struct ifreq *ifr_iterator = ifc.ireq; int i = 0; size_t len; while (i < ifc.ifc_len) { /* DO STUFF */ // Maybe some more filtering based on SIOCGIFFLAGS // Your code // Use ifr_iterator-> ... len = IFNAMSIZ + ifr_iterator->ifr_addr.sa_len; ifr_iterator = (struct ifreq *)((char *)ifr_iterator + len); i += len; } 

查看( Windows特定的 ) IP Helper API – 幸运的是,您在Windows上不需要ioctl