2010-10-11 107 views
3

我認爲無法使用套接字來枚舉系統上的每個網絡接口及其分配的IP地址。它是否正確?枚舉分配給網絡接口的每個IP地址

我的意思是,在Linux中,這可能是:

eth0: 192.168.1.5 
wlan0: 192.168.0.5 
lo: 127.0.0.1 

我不在乎接口名稱,只是分配的IP地址。

我記得過去在Windows中使用Win32(儘管我不記得如何)做過這個。但是有沒有辦法以便攜的方式來做到這一點?

回答

10

這裏有一個良好的開端:

#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <ifaddrs.h> 
#include <stdio.h> 
void 
print_sockaddr(struct sockaddr* addr,const char *name) 
{ 
    char addrbuf[128] ; 

    addrbuf[0] = 0; 
    if(addr->sa_family == AF_UNSPEC) 
     return; 
    switch(addr->sa_family) { 
     case AF_INET: 
      inet_ntop(addr->sa_family,&((struct sockaddr_in*)addr)->sin_addr,addrbuf,sizeof(addrbuf)); 
      break; 
     case AF_INET6: 
      inet_ntop(addr->sa_family,&((struct sockaddr_in6*)addr)->sin6_addr,addrbuf,sizeof(addrbuf)); 
      break; 
     default: 
      sprintf(addrbuf,"Unknown (%d)",(int)addr->sa_family); 
      break; 

    } 
    printf("%-16s %s\n",name,addrbuf); 
} 

void 
print_ifaddr(struct ifaddrs *addr) 
{ 
    char addrbuf[128] ; 

    addrbuf[0] = 0; 
    printf("%-16s %s\n","Name",addr->ifa_name); 
    if(addr->ifa_addr != NULL) 
     print_sockaddr(addr->ifa_addr,"Address"); 
    if(addr->ifa_netmask != NULL) 
     print_sockaddr(addr->ifa_netmask,"Netmask"); 
    if(addr->ifa_broadaddr != NULL) 
     print_sockaddr(addr->ifa_broadaddr,"Broadcast addr."); 
    if(addr->ifa_dstaddr != NULL) 
     print_sockaddr(addr->ifa_dstaddr,"Peer addr."); 
    puts(""); 
} 

int main(int argc,char *argv[]) 
{ 
    struct ifaddrs *addrs,*tmp; 

    if(getifaddrs(&addrs) != 0) { 
     perror("getifaddrs"); 
     return 1; 
    } 
    for(tmp = addrs; tmp ; tmp = tmp->ifa_next) { 
     print_ifaddr(tmp); 
    } 

    freeifaddrs(addrs); 

    return 0; 
} 
+1

+1。不知道getifaddrs()/ freeifaddrs() – ninjalj 2010-10-11 21:26:31

+0

優秀的答案! +1 – slezica 2010-10-12 01:19:56

+0

這就是我所需要的,謝謝!但它只適用於Linux,我說得對嗎? winapi相當於什麼? – conejoroy 2010-10-12 06:03:08

0

使用gethostname()來檢索機器的本地DNS名稱,然後將該名稱傳遞到gethostbyname()以獲取其本地IP地址。

如果操作系統支持IPv6,請查看getaddrinfo()函數,而不是gethostbyname()

+1

這裏我手動編輯的主機名解析到我的靜態LAN IP地址(可以說192.168.0.2),但究竟如何這個行爲上的另一個系統?我的意思是...主機名解析爲127.0.0.1還是默認使用哪個接口的IP? – conejoroy 2010-10-12 05:54:16

+0

使用IP地址作爲主機名調用'gethostbyname()'將不起作用,AFAIK。你可以使用'gethostbyaddr()',但是這會返回一個'hostent'結構,它只包含你最初指定的IP。要枚舉可用的IP,您必須使用機器的實際主機名。否則,你將不得不使用操作系統特定的API來直接枚舉網絡接口(在Windows上,查看'GetAdapterAddresses()'和相關函數)。 – 2010-10-13 20:02:24

0

查看ioctl()函數。如果我沒有記錯,你可以用它來獲取任何接口的信息,以及獲取可用的接口。

雖然我不記得正確的調用。與fcntl()一樣,它需要一個請求參數和確定其行爲的變量參數。

0

在Linux上,通過NETLINK套接字訪問該信息。請參閱libnetlink(3),netlink(7)和rtnetlink(7)的手冊頁。

這樣做更簡單一些,可以通過ioctl()來實現。 SIOCGIFCONF是你想要的。請參閱netdevice的手冊頁(7)。這一個適用於其他* nixes。