getaddrinfo调用有许多有趣的标志.我想知道AI_V4MAPPED标志的用途是什么.在没有系统的情况下,我似乎能够获得getaddrinfo来生成:: ffff:nnnn表单地址,正如我在设置此标志时所期望的那样.我期待错误的事吗?我看到了虫子吗?
特别是,如果我要求AF_INET6系列地址并指定AI_V4MAPPED,我希望看到只有DNS A(IPv4地址)记录的主机的:: ffff:nnnn地址.我通常也会期望,如果我指定AI_ALL,我将获得主机的DNS AAAA(IPv6地址)记录和:: ffff:nnnn形式的DNS A记录.
我再次期待这里所有错误的事情吗?
我在Fedora 11上测试了这个 - glibc 2.10.1和OS X 10.4.
我得到了你期望得到的东西,在Debian Lenny(glibc 2.7) - 有一个例外 - 如果我指定AI_V4MAPPED
没有AI_ALL
,并且我查找的主机名有CNAME指向A记录,我不会得到那些返回.如果AI_ALL
还指定了它,或者主机名与A记录直接关联,则它可以正常工作.
我不知道为什么 - 也许这是一个glibc错误?
这是我的测试程序:
#include#include #include #include #include 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; }