ここに私のコードです。getaddrinfo()によって返されたリンクリストに重複するaddrinfoオブジェクトがあるのはなぜですか?
#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
の場合は、コード内に存在するが、::1
で始まる/etc/hosts
の行がコメントアウトされている場合、実際に重複したエントリが消えます。
$ 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のエントリのみを選択するために使用された場合でも、理由を知っていただきたいと思います。
私の/ etc/hostsはあなたのものとよく似ています。私はなぜそれが重複した 'addrinfo'sを返すべきか理解していません。 2番目のエントリはIPv6アドレス ':: 1'です。私のコードでは、特にヒントを使ってIPv4アドレスだけを選択しています。 –
コードから 'hints.ai_family = AF_INET'を削除すると、重複したエントリがないことを示す別の出力を追加しました。重複したエントリは、コード内で 'hints.ai_family = AF_INET'でIPv4エントリのみを選択した場合にのみ表示されます。 –
@LoneLearner:IPv6エントリをコメントアウトしてみてください。私のマシン上にこのような問題はないので、ディストリビューション(またはglibcバージョン?)固有の[this](https://bugzilla.redhat.com/show_bug.cgi?id=496300)のようなものかもしれません。 –