假設我正在運行一個名爲IpAddresses.c的程序。我希望該程序根據每個接口獲取此設備具有的所有IP地址。就像ifconfig。我怎樣才能做到這一點?如何才能知道C中接口的IP地址?
我對ioctl瞭解不多,但我讀過它可能對我有幫助。
假設我正在運行一個名爲IpAddresses.c的程序。我希望該程序根據每個接口獲取此設備具有的所有IP地址。就像ifconfig。我怎樣才能做到這一點?如何才能知道C中接口的IP地址?
我對ioctl瞭解不多,但我讀過它可能對我有幫助。
只需使用getifaddrs()。這裏有一個例子:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
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
爲什麼你有2個eth0?順便說一句,thk爲您的答案 – gvalero87 2010-11-10 00:32:52
@ gvalero87第一eth0告訴網卡通過互聯網進行通信。第二個eth0通過專用連接(光線路)與第三方進行通信。這是網絡管理員放在一起的路由表中的一個設置。 – chrisaycock 2010-11-10 01:33:46
檢查出(Windows特定)IP Helper API - 幸運的是,您不需要ioctl
這在Windows上。
你可以嘗試這樣的事情:
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);
}
for (int i=0; i < ifc.ifc_len/sizeof(struct ifreq); ++i) {
if (ifr[i].ifr_addr.sa_family != AF_INET) {
continue;
}
// Maybe some more filtering based on SIOCGIFFLAGS
// Your code
}
請注意,此代碼將在BSD上失敗,其中ifreq結構的大小是可變的。你不能假設'ifc.ifc_len/sizeof(struct ifreq)'會給你接口的數量。相反,你需要像這樣迭代列表中的元素:struct ifreq * ifr_iterator = ifc.ireq; size_t len; while(i
@Joakim所以這意味着''#define ifc_req ifc_ifcu.ifcu_req/*結構數組ret'd * /''技術上不是一個數組,因爲大小不一樣?看來5.9增加了更多的東西。此外,ifconfig.c代碼似乎沒有SIOCGIFCONF – GorillaApe 2016-07-15 20:34:45
@GorillaApe在一個系統上它可能是一個數組,另一個不是。我的觀點有不同的實現。在Linux上,這是一個數組,每個項目的大小都是固定的,但在BSD上,每個項目的大小可能會有所不同,因此正確的方法是始終使用長度字段。如果你想要的便攜式代碼。 – Joakim 2016-08-27 11:19:16
看到這個其他堆棧溢出問題,Enumerating each IP address assigned to network interfaces。
總之,您可以使用:
ioctl(SIOCGIFCONF)
- >傳統的ioctlgetifaddrs()
- >從的BSDi,現在也可以在Linux和BSD的。下面是一些Linux的示例代碼,可以幫助你。
#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#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;
}
感謝您的ioctl選擇。然而,我永遠不知道,當我應該使用'ioctl'和'getifaddrs'時。 – Youda008 2015-12-27 09:25:31
我相信即使它不符合任何單一標準,'ioctl'也可能稍微更具可移植性。它在大多數Unix和類Unix系統上得到支持,並且'ioctl'函數調用首次出現在版本7 AT&T UNIX中。我相信'getifaddrs'在BSD和Linux中得到支持,並首次出現在glibc 2.3中。 – jschmier 2016-01-04 15:40:43
這也適用於Android,因爲某些原因沒有'ifaddrs'的東西,但不在OS X上。[這是一個例子](https://gist.github.com/OrangeTide/909204)都。 – Grishka 2016-10-30 03:22:37
使用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);
只因爲我自己得到了分割錯誤。
我得到了分割錯誤。這段代碼修復了它。 – 2017-01-10 11:20:23
你的平臺是什麼? – 2010-11-09 22:39:22