代码之家  ›  专栏  ›  技术社区  ›  user541686

getaddrinfo(),IPv6没有意义

  •  1
  • user541686  · 技术社区  · 7 年前

    我不明白为什么 getaddrinfo

    22:B8:00:00:00:00:00:00:00:00:00:00:00:00 ,但我希望 01 localhost 应决心 ::1 .

    同时 sa_data 只有14个字节,而IPv6地址是16个字节,所以最后几个字节似乎总是被截断,函数 不能 返回IPv6地址?

    有人能解释一下发生了什么事吗?我应该如何在IPv6中使用此功能?

    #include <stdio.h>
    #include <WinSock2.h>
    #include <WS2TCPIP.h>
    #pragma comment(lib, "WS2_32")
    
    int main(int argc, char *argv[])
    {
        WSADATA wsadata;
        WSAStartup(0x0002, &wsadata);
        addrinfo addr_hints = { 0, PF_INET6, SOCK_DGRAM, IPPROTO_UDP }, *addrs_out;
        getaddrinfo("localhost", "8888", &addr_hints, &addrs_out);
        fprintf(stderr,
            "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 0]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 1]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 2]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 3]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 4]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 5]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 6]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 7]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 8]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[ 9]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[10]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[11]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[12]),
            static_cast<unsigned char>(addrs_out->ai_addr->sa_data[13]));
        freeaddrinfo(addrs_out);
        return 0;
    }
    
    2 回复  |  直到 7 年前
        1
  •  6
  •   Jeff    7 年前

    sockaddr 结构定义供参考:

    struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
    };
    
    
    struct sockaddr_in6 {
        short   sin6_family;
        u_short sin6_port;
        u_long  sin6_flowinfo;
        struct  in6_addr sin6_addr;
        u_long  sin6_scope_id;
    };
    

    什么时候 ai_family == AF_INET6 ai_addr struct sockaddr_in6 . 打印的前几个字节是 sin6_port sin6_flowinfo . IPv6地址在后面。

    编辑以添加:

    ai_地址 直接使用以下函数 bind() getnameinfo() . 您通常不需要深入了解结构定义的细节。例如,我会使用 getnameinfo() NI_NUMERICHOST 获取可打印的地址。

        2
  •  1
  •   RbMm    7 年前

    sockaddr sockaddr结构。该结构在

    所以我们需要先检查一下 sa_family 属于 sockaddr ai_family 从…起 addrinfo (在此基础上,它必须相等)并基于此需要从 (就像这样 void*

    addrinfo *addrs_out, *addr;
    
    if (getaddrinfo("localhost", "8888", 0, &addrs_out) == NOERROR)
    {
        addr = addrs_out;
    
        CHAR buf[256], *sz, srv[128];
        ULONG n;
        PUCHAR Byte;
    
        do 
        {
            union {
                sockaddr* ai_addr;
                SOCKADDR_IN* pa;
                SOCKADDR_IN6* pa6;
            };
    
            ai_addr = addr->ai_addr;
    
            if (addr->ai_family != ai_addr->sa_family)
            {
                __debugbreak();
            }
    
            switch (addr->ai_family)
            {
            case AF_INET6:
                Byte = pa6->sin6_addr.u.Byte, n = RTL_NUMBER_OF(pa6->sin6_addr.u.Byte), sz = buf;
                do 
                {
                    sz += sprintf(sz, "%02X:", *Byte++);
                } while (--n);
    
                sz[-1] = 0;
                DbgPrint("AF_INET6: %s\n", buf);
                break;
    
            case AF_INET:
                if (0 <= RtlIpv4AddressToStringExA(&pa->sin_addr.S_un.S_addr, pa->sin_port, buf, &(n = RTL_NUMBER_OF(buf))))
                {
                    DbgPrint("AF_INET: %s\n", buf);
                }
                break;
            }
    
            // alt print
            if (getnameinfo(ai_addr, (socklen_t)addr->ai_addrlen, buf, RTL_NUMBER_OF(buf), srv, RTL_NUMBER_OF(srv), NI_NUMERICHOST ) == NOERROR)
            {
                DbgPrint("%s:%s\n", buf, srv);
            }
    
        } while (addr = addr->ai_next);
    
        freeaddrinfo(addrs_out);
    }