【发布时间】:2017-01-21 19:16:38
【问题描述】:
这是我的代码。
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
int main()
{
struct addrinfo hints, *res, *p;
int error;
memset(&hints, 0, sizeof hints);
/* If we comment or remove the following line, the duplicate entries
* disappear */
hints.ai_family = AF_INET;
error = getaddrinfo("localhost", "http", &hints, &res);
if (error != 0) {
printf("Error %d: %s\n", error, gai_strerror(error));
return 1;
}
for (p = res; p != NULL; p = p->ai_next)
{
if (p->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *) p->ai_addr;
char ip[INET_ADDRSTRLEN];
printf("ai_flags: %d; ai_family: %d; ai_socktype: %d; "
"ai_protocol: %2d; sin_family: %d; sin_port: %d; "
"sin_addr: %s; ai_canonname: %s\n",
p->ai_flags, p->ai_family, p->ai_socktype,
p->ai_protocol, addr->sin_family, ntohs(addr->sin_port),
inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN),
p->ai_canonname);
} else if (p->ai_family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) p->ai_addr;
char ip[INET6_ADDRSTRLEN];
printf("ai_flags: %d; ai_family: %d; ai_socktype: %d; "
"ai_protocol: %2d; sin6_family: %d; sin6_port: %d; "
"sin6_addr: %s; ai_canonname: %s\n",
p->ai_flags, p->ai_family, p->ai_socktype,
p->ai_protocol, addr->sin6_family, ntohs(addr->sin6_port),
inet_ntop(AF_INET6, &addr->sin6_addr, ip, INET6_ADDRSTRLEN),
p->ai_canonname);
}
}
return 0;
}
这是输出。
$ gcc -std=c99 -D_POSIX_SOURCE -Wall -Wextra -pedantic bar.c && ./a.out
ai_flags: 0; ai_family: 2; ai_socktype: 1; ai_protocol: 6; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
ai_flags: 0; ai_family: 2; ai_socktype: 2; ai_protocol: 17; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
ai_flags: 0; ai_family: 2; ai_socktype: 1; ai_protocol: 6; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
ai_flags: 0; ai_family: 2; ai_socktype: 2; ai_protocol: 17; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
输出显示第 1 项和第 3 项完全相同。同样,第 2 个和第 4 个条目完全相同。为什么我们会在结果中出现这些重复项?
如果我们从代码中注释或删除以下行,那么重复的条目就会消失。
/* If we comment or remove the following line, the duplicate entries
* disappear */
/* hints.ai_family = AF_INET; */
这是本例中的输出。
$ gcc -std=c99 -D_POSIX_SOURCE -Wall -Wextra -pedantic bar.c && ./a.out
ai_flags: 0; ai_family: 10; ai_socktype: 1; ai_protocol: 6; sin6_family: 10; sin6_port: 80; sin6_addr: ::1; ai_canonname: (null)
ai_flags: 0; ai_family: 10; ai_socktype: 2; ai_protocol: 17; sin6_family: 10; sin6_port: 80; sin6_addr: ::1; ai_canonname: (null)
ai_flags: 0; ai_family: 2; ai_socktype: 1; ai_protocol: 6; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
ai_flags: 0; ai_family: 2; ai_socktype: 2; ai_protocol: 17; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
这就是我的/etc/hosts 的样子。
$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 debian1
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
如果hints.ai_family = AF_INET 出现在代码中,但如果/etc/hosts 中以::1 开头的行被注释掉,那么重复的条目确实会消失。
$ gcc -std=c99 -D_POSIX_SOURCE -Wall -Wextra -pedantic bar.c && ./a.out
ai_flags: 0; ai_family: 2; ai_socktype: 1; ai_protocol: 6; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
ai_flags: 0; ai_family: 2; ai_socktype: 2; ai_protocol: 17; sin_family: 2; sin_port: 80; sin_addr: 127.0.0.1; ai_canonname: (null)
但我仍然想知道为什么 /etc/hosts 中的 IPv6 条目会导致重复条目,即使 hints.ai_family = AF_INET 仅用于选择 IPv4 条目。
【问题讨论】: