getaddrinfo调用有许多有趣的标志。我想知道AI_V4MAPPED标志的用途是什么。在没有系统的情况下,我似乎能够获得getaddrinfo来生成:: ffff:n.n.n.n表单地址,就像我设置此标志时所期望的那样。我期待错误的事吗?我看到了虫子吗?
特别是,如果我要求AF_INET6系列地址并指定AI_V4MAPPED,我希望看到只有DNS A(IPv4地址)记录的主机的:: ffff:n.n.n.n地址。我通常也会期望,如果我指定AI_ALL,我将获得主机的DNS AAAA(IPv6地址)记录和:: ffff:n.n.n.n表格中的DNS A记录。
同样,我在这里期待所有错误的事情吗?
我在Fedora 11上测试了这个 - glibc 2.10.1和OS X 10.4。
答案 0 :(得分:6)
我得到了你期望得到的东西,Debian Lenny(glibc 2.7) - 有一个例外 - 如果我指定AI_V4MAPPED
没有AI_ALL
,我查找的主机名有CNAME指向在A记录中,我没有得到那些返回。如果还指定了AI_ALL
,或者主机名与A记录直接关联,则它可以正常工作。
我不知道为什么 - 也许这是一个glibc错误?
这是我的测试程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct addrinfo hints = { 0 };
struct addrinfo *res, *res_c;
int err;
char name[INET6_ADDRSTRLEN];
if (argc < 2)
{
return 1;
}
hints.ai_family = AF_INET6;
hints.ai_flags = AI_V4MAPPED | AI_ALL;
err = getaddrinfo(argv[1], NULL, &hints, &res);
if (err)
{
printf("getaddrinfo: %s\n", gai_strerror(err));
return 1;
}
for (res_c = res; res_c; res_c = res_c->ai_next)
{
const void *addr;
int port;
struct protoent *proto;
switch (res_c->ai_family)
{
case AF_INET6:
addr = &((struct sockaddr_in6 *)(res_c->ai_addr))->sin6_addr;
port = ((struct sockaddr_in6 *)(res_c->ai_addr))->sin6_port;
printf("AF_INET6\t");
break;
case AF_INET:
addr = &((struct sockaddr_in *)(res_c->ai_addr))->sin_addr;
port = ((struct sockaddr_in *)(res_c->ai_addr))->sin_port;
printf("AF_INET\t");
break;
default:
addr = NULL;
printf("(%d)\t", res_c->ai_family);
}
proto = getprotobynumber(res_c->ai_protocol);
if (proto)
{
printf("%s\t", proto->p_name);
}
else
{
printf("(%d)\t", res_c->ai_protocol);
}
switch (res_c->ai_socktype)
{
case SOCK_STREAM:
printf("SOCK_STREAM\t");
break;
case SOCK_DGRAM:
printf("SOCK_DGRAM\t");
break;
default:
printf("(?socktype?)\t");
break;
}
if (addr && inet_ntop(res_c->ai_family, addr, name, sizeof name))
printf("addr = %s", name);
if (addr)
printf(",%d", port);
printf("\n");
}
return 0;
}
答案 1 :(得分:4)
根据我的经验,AI_V4MAPPED
在Mac OS X 10.6上不起作用。如果您提供hints.ai_family = AF_INET6
和hints.ai_flags = AI_V4MAPPED
,则会始终返回EAI_NONAME
,并且gai_strerror()
会打印“提供的节点名称或服务名称,或者不知道”。
它在OS X 10.7上正常工作。
在这里发布这个以防它可以帮助某人,即使你在使用Fedora。