我编写了以下测试程序,无法理解我得到的输出:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
int main(int argc, char** argv) {
struct addrinfo* results;
struct addrinfo hints;
char buf[INET6_ADDRSTRLEN+1];
if (argc != 2) {
exit(-1);
}
memset((char*) &hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
int ret = getaddrinfo(NULL, argv[1], &hints, &results);
if (ret) {
fprintf(stderr, "%s\n", gai_strerror(ret));
exit(-1);
}
for (struct addrinfo* ai = results; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family == AF_INET) {
inet_ntop(AF_INET, ai, buf, INET_ADDRSTRLEN);
} else {
inet_ntop(AF_INET6, ai, buf, INET6_ADDRSTRLEN);
}
printf("%s\n", buf);
}
freeaddrinfo(results);
return 0;
}
在我的Fedora 23机器上,这将打印:
1.0.0.0
100:0:a00:0:100:0:600:0
我的理解是,返回的IP地址应为INADDR_ANY
和IN6ADDR_ANY_INIT
,两者都应具有值0
,即预期输出应为0.0.0.0
并且::0
。有人可以向我解释这里发生了什么吗?
另一个相关的问题是,如果我的某个接口有host.domain.dom
解析的IP,并且我不确定该域是否具有IPv6地址,我该如何获得{{1}我可以用来监听这个域的IPv4和IPv6地址但不绑定任何其他IP的结构?将主机名提供给sockaddr
是否正确,即使在这种情况下getaddrinfo
标志被忽略了?
答案 0 :(得分:3)
你不应该将ai
本身作为inet_ntop
的论据;您应该提供指向实际网络地址的指针,而不是指向addrinfo
结构的指针。 inet_ntop()
需要in_addr
和in6_addr
结构,因此根据ai->ai_addr
向sockaddr_in*
或sockaddr_in6*
输入ai->ai_family
,然后分别传递其sin_addr
或sin6_addr
字段的地址。
if (ai->ai_family == AF_INET) {
inet_ntop(AF_INET, &(((sockaddr_in*)(ai->ai_addr))->sin_addr), buf, INET_ADDRSTRLEN);
} else {
inet_ntop(AF_INET6, &(((sockaddr_in6*)(ai->ai_addr))->sin6_addr), buf, INET6_ADDRSTRLEN);
}
对于你的第二个问题,我相信这会回答: