2010-10-11 48 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。