【问题标题】:Where is the ip address in IP_ADAPTER_ADDRESSES_LHIP_ADAPTER_ADDRESSES_LH 中的 ip 地址在哪里
【发布时间】:2019-01-22 19:08:03
【问题描述】:

根据这个问题:

How to get local IP address of Windows system?

@Remy Lebeau 回答说GetAdaptersAddresses() 是一种使用 C++ 在 Windows 中获取本地计算机 IP 地址的方法。

我编译了示例,示例没有打印出机器的本地IP地址。我查看了函数返回的结构 (IP_ADAPTER_ADDRESSES_LH),我惊讶地发现我没有看到任何对实际 IP 地址所在位置的引用。

我的问题是,IP_ADAPTER_ADDRESSES_LH 结构中的 IP 地址在哪里?

【问题讨论】:

    标签: c++ windows winapi


    【解决方案1】:

    我编译了示例,示例并没有打印出机器的本地IP地址。

    GetAdaptersAddresses() 一直对我很好。

    IP_ADAPTER_ADDRESSES_LH 结构中的 IP 地址在哪里?

    结构中可能有 许多 个 IP 地址,具体取决于您感兴趣的 IP 地址的种类 - 单播、任播、多播或 DnsServer。对于本地分配的 IP,您通常只使用单播地址:

    • IP_ADAPTER_ADDRESSES_LH::FirstUnicastAddress 字段指向IP_ADAPTER_UNICAST_ADDRESS_LH 结构的链表,每个 IP 地址对应一个条目。使用IP_ADAPTER_UNICAST_ADDRESS_LH::Next字段循环遍历列表(MSDN例子展示了这样一个循环,但是它只计算列表中元素的个数,不会打印出列表的内容)。

      李>
    • IP_ADAPTER_UNICAST_ADDRESS_LH::Address 字段包含SOCKET_ADDRESS 格式的实际 IP 地址。

    • SOCKET_ADDRESS::lpSockaddr 字段是一个SOCKADDR* 指针。您可以将其按原样传递给bind() 等套接字 API。

    • 1234563分别是 IPv4 或 IPv6(使用 SOCKADDR::sa_family 字段来确定正确的类型 - AF_INET 用于 sockaddr_inAF_INET6 用于 sockaddr_in6)。然后您可以根据需要访问sockaddr_in::sin_addrsockaddr_in6::sin6_addr字段,其中包含IP地址的实际字节。

    例如:

    PIP_ADAPTER_ADDRESSES pAddresses = ...; // allocate buffer as needed...
    ULONG ulSize = ...; // size of allocated buffer...
    
    if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, NULL, pAddresses, &ulSize) == 0)
    {
        for (PIP_ADAPTER_UNICAST_ADDRESS_LH *pAddress = pAddresses->FirstUnicastAddress;
            pAddress != NULL;
            pAddress = pAddress->Next)
        {
            SOCKADDR *pSockAddr = pAddress->Address.lpSockaddr;
            switch (pSockAddr->sa_family)
            {
                case AF_INET: {
                    sockaddr_in *pInAddr = (sockaddr_in*) pSockAddr;
                    // use pInAddr->sin_addr as needed...
                    break;
                }
    
                case AF_INET6: {
                    sockaddr_in6 *pIn6Addr = (sockaddr_in6*) pSockAddr;
                    // use pIn6Addr->sin6_addr as needed...
                    break;
                }
            }
        }
    }
    
    // free pAddresses as needed ...
    

    【讨论】:

    • 非常感谢您的详细解答!这工作得很好
    猜你喜欢
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 2014-11-29
    • 1970-01-01
    相关资源
    最近更新 更多