枚举分配给网络接口的每个IP地址

时间:2010-10-11 20:21:08

标签: c windows linux sockets networking

我认为没有办法只使用套接字枚举我的系统上的每个网络接口及其分配的IP地址。这是对的吗?

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

eth0: 192.168.1.5
wlan0: 192.168.0.5
lo: 127.0.0.1

我不关心接口名称,只关心分配的IP地址。

我记得过去曾在Windows中使用Win32完成此操作(虽然我不记得如何)。但是有一种方法可以通过便携方式实现吗?

4 个答案:

答案 0 :(得分: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 :(得分:0)

使用gethostname()检索计算机的本地DNS名称,然后将该名称传递给gethostbyname()以获取其本地IP地址。

如果操作系统支持IPv6,请查看getaddrinfo()功能,而不是gethostbyname()

答案 2 :(得分:0)

查看ioctl()功能。如果我没记错,您可以使用它来获取任何接口的信息,以及获取可用的接口。

我不记得正确的调用。与fcntl()一样,它采用请求参数和可变参数来确定其行为。

答案 3 :(得分:0)

在Linux上,通过NETLINK套接字访问该信息。请参阅libnetlink(3),netlink(7)和rtnetlink(7)的手册页。

更容易实现的方法是通过ioctl()来实现。 SIOCGIFCONF就是您想要的。请参见netdevice(7)的手册页。这个适用于其他一些* nixes。