IPv6 的 getaddrinfo 总是失败,错误代码为 11268096

问题描述

编辑:在检查 IPv6 Test 时,我发现我的 ISP 不提供 IPv6...否则这段代码很好

getaddrinfo() 对于 IPv6 总是失败,错误代码为 11268096,但对于 IPv4 是成功的。

设置 Hint.ai_family = AF_INET6; 是触发错误的原因,但我不知道为什么。

另外,我如何获得数字中的 sin_port/sin6_port?我总是得到端口 0。(正如@Remy Lebeau 指出的,我只要求域的 IP,所以它不会输出端口......)

void GetAddrInfoFromHostNameIPV6(const char* DomainName,addrinfo* Result,bool& IsSuccessful)
{
    IsSuccessful = false;
    addrinfo Hint;
    addrinfo* Return = nullptr;
    int ErrorCode;

    memset(&Hint,sizeof(Hint));
    Hint.ai_family = AF_INET6;
    Hint.ai_socktype = SOCK_STREAM;
    //Hint.ai_socktype = SOCK_DGRAM;

    ErrorCode = getaddrinfo(DomainName,NULL,&Hint,&Return) << '\n';
    if (ErrorCode != 0)
    {
        std::cout << "\n Error GetAddrInfoFromHostNameIPV6() Failed with Error Code: " << ErrorCode << " in GetAddrInfoFromHostName In: NW_P!";
    }
    else
    {
        *Result = *Return;
        char IpAddress[INET6_ADDRSTRLEN];
        uint16_t Port;
        inet_ntop(AF_INET6,&((sockaddr_in6*)((Result)->ai_addr))->sin6_addr,IpAddress,INET6_ADDRSTRLEN);
        Port = *(&((sockaddr_in6*)(Result->ai_addr))->sin6_port);
        std::cout << "\n IPV6 Address of Domain '" << DomainName << "' Is " << IpAddress << " With Port: " << Port;

        IsSuccessful = true;
    }

    if (!IsSuccessful)// For the safe of readability
    {
        std::cout << "\n Error GetAddrInfoFromHostName() Failed in NW_P!\n";
    }
}

解决方法

您将错误代码向左移位 10 位,然后再将其分配给 ErrorCode

十进制 11268096 是二进制 101010111111000000000000。注意到右边所有额外的零了吗?

您需要在 << '\n' 返回后去掉 getaddrinfo(),它不属于那里,因为您没有在该行代码中将错误代码输出到 std::cout

去掉位移,真正的错误码是11004(二进制10101011111100),即WSANO_DATA

有效名称,没有请求类型的数据记录。请求的名称有效并且在数据库中找到,但没有正确的关联数据正在解析。通常的例子是使用 DNS(域名服务器)的主机名到地址转换尝试(使用 gethostbynameWSAAsyncGetHostByName)。返回一条 MX 记录但没有 A 记录——表明主机本身存在,但不能直接访问。

您可以将错误代码传递给 gai_strerror() 以获得错误消息输出的人类可读字符串,例如:

std::cout << "\n Error GetAddrInfoFromHostNameIPV6() Failed with Error Code: " << ErrorCode << " (" << gai_strerror(ErrorCode) << ") in GetAddrInfoFromHostName In: NW_P!";

至于端口号为 0,您不是要求 getaddrinfo() 解析任何服务名称/端口字符串作为输入(pServiceName 参数为 NULL),您只是要求翻译域名称转换为 IP,因此它不会输出任何端口号。域本身不使用端口号。端口号由在域/IP 指向的服务器上运行的服务(HTTP 等)使用。


附带说明,您正在泄露 addrinfo 输出的 getaddrinfo() 列表。使用完列表后,您需要调用 freeaddrinfo()