2010-09-17 15 views
7

我有一个程序,其中一个外部组件向我传递一个包含IP地址的字符串。然后我需要把它变成一个URI。对于IPv4来说,这很容易;我预先安装http://并附加/。但是,对于IPv6,我还需要将它括在括号[]中。使用标准C socket告诉文本字符串是IPv6地址还是IPv4地址API

是否有标准套接字API调用来确定地址的地址族?

+0

我知道它不是套接字API的一部分,但是如果IP4和IP6是唯一的可能性,你不能用'strlen'来做这个吗? ;-) – 2010-09-17 16:43:48

+0

@Steve Jessop考虑例如ff02 :: 2和8.8.8.8 – nos 2010-09-17 17:41:32

+0

@nos:够公平的,没有意识到前者是一个有效的地址。更一般地说,是否有一些方法来检查字符串,这比使用套接字API更简单的代码?在这种情况下,不需要包含解析地址的结构。 – 2010-09-17 17:51:16

回答

13

使用getaddrinfo(),并设置标志暗示AI_NUMERICHOST,家庭AF_UNSPEC,在从的getaddrinfo全成返回,所产生的结构addrinfo中.ai_family构件将或者AF_INET或AF_INET6。

EDIT,小例子

#include <sys/types.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <netdb.h> 

int main(int argc, char *argv[]) 
{ 
    struct addrinfo hint, *res = NULL; 
    int ret; 

    memset(&hint, '\0', sizeof hint); 

    hint.ai_family = PF_UNSPEC; 
    hint.ai_flags = AI_NUMERICHOST; 

    ret = getaddrinfo(argv[1], NULL, &hint, &res); 
    if (ret) { 
     puts("Invalid address"); 
     puts(gai_strerror(ret)); 
     return 1; 
    } 
    if(res->ai_family == AF_INET) { 
     printf("%s is an ipv4 address\n",argv[1]); 
    } else if (res->ai_family == AF_INET6) { 
     printf("%s is an ipv6 address\n",argv[1]); 
    } else { 
     printf("%s is an is unknown address format %d\n",argv[1],res->ai_family); 
    } 

    freeaddrinfo(res); 
    return 0; 
} 

$ ./a.out 127.0.0.1 
127.0.0.1 is an ipv4 address 
$ ./a.out ff01::01 
ff01::01 is an ipv6 address 
16

类。您可以使用inet_pton()尝试首先将字符串解析为IPv4(AF_INET),然后是IPv6(AF_INET6)。返回代码将让您知道函数是否成功,并且字符串因此包含尝试类型的地址。

例如:

#include <arpa/inet.h> 
#include <stdio.h> 

static int 
ip_version(const char *src) { 
    char buf[16]; 
    if (inet_pton(AF_INET, src, buf)) { 
     return 4; 
    } else if (inet_pton(AF_INET6, src, buf)) { 
     return 6; 
    } 
    return -1; 
} 

int 
main(int argc, char *argv[]) { 
    for (int i = 1; i < argc; ++i) { 
     printf("%s\t%d\n", argv[i], ip_version(argv[i])); 
    } 

    return 0; 
} 
+1

getaddrinfo()有一堆开销,但基本上也调用inet_pton()。 inet_pton()真的是你所需要的,恕我直言,这个问题的最佳答案。它也不需要清理功能。 – rockdaboot 2014-08-20 08:46:59

相关问题