是否有必要尝试连接getaddrinfo()返回的所有地址?

Beej的Simple Client示例代码迭代从getaddrinfo()返回的所有IP地址,直到它可以连接到第一个IP地址。 请参阅下面的代码。

这总是必要的,还是可以假设我们只需要尝试连接到getaddrinfo()返回的第一个地址?

memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // ------------------------------------------------------------ // loop through all the results and connect to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("client: socket"); continue; } if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("client: connect"); continue; } break; } 

是的,您应该迭代所有地址 – 特别是,考虑目标主机启用IPv6地址但本地主机没有启用IPv6地址的情况。 getaddrinfo()将返回AF_INET6系列地址,但是socket()connect()调用将失败。

您的主机也可能支持实现SOCK_STREAM多个协议(例如,除TCP之外的SCTP),而目标主机不支持 – 因为您尚未设置提示结构的ai_protocol成员,代表支持SOCK_STREAM套接字的所有协议的地址将被退回

除了上面给出的其他答案之外,考虑一般情况,对于较大的网站等,可能会发布多个A记录,以用于冗余目的。 如果第一个地址的connect()失败,您也想尝试其他地址。

让我们以这种方式看看山雀……你要连接的服务器主机可能有几个与之关联的地址,但实际的服务器程序只监听其中一个地址。 如果您的客户端不知道服务器程序正在侦听的确切地址,则必须先尝试主机所具有的所有地址,直到找到正确的地址并进行连接。

是的,你应该遍历所有这些 – 不能保证地址中的第一个(或你选择的任何一个)实际上是有效的。 这就是为什么它在教程中完成的原因。

假设您是socket的新手,此时此刻。 是的,这很重要,因为在使用getaddrinfo之后,您可以检索地址信息以进一步validation。