如何从 SOCKADDR 结构中获取 IPv4 地址?

How to get IPv4 address from SOCKADDR structure?

我不知道如何从 IP_ADAPTER_UNICAST_ADDRESS_LHAddress 字段中获取实际的 IP v4 地址(例如 192.168.1.1 或其对应的 32 位整数压缩形式)结构体。我进入了链接列表和相应的 MSDN 链接的兔子洞,但 SOCKADDR 是它切断的地方。 SOCKADDR 是通用数据持有者,必须将其转换为 IPv4 变体才能获得数据的结构化视图。

问题是,我找不到哪个结构是 SOCKADDR 的 IPv4 映射。已尝试 in_addr,获取垃圾值。

auto pAddresses = static_cast<IP_ADAPTER_ADDRESSES*>(malloc(defaultBufferSize));
    ULONG outBufLen = defaultBufferSize;
    constexpr ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
    auto result = GetAdaptersAddresses(AF_INET /* Only IP v4 since no cameras use v6 yet */, flags, nullptr, pAddresses, &outBufLen);

    uint32_t ipV4Address = 0;

    // Iterating over the returned adapter info structures
    for (auto currentInterfaceInfo = pAddresses; currentInterfaceInfo != nullptr; currentInterfaceInfo = currentInterfaceInfo->Next)
    {
        if (currentInterfaceInfo->IfType != IF_TYPE_IEEE80211 || currentInterfaceInfo->Ipv4Enabled != 1 || currentInterfaceInfo->ReceiveOnly != 0)
            continue;

        if (currentInterfaceInfo->FirstUnicastAddress)
        {
            for (auto addressInfo = currentInterfaceInfo->FirstUnicastAddress; addressInfo != nullptr; addressInfo = currentInterfaceInfo->FirstUnicastAddress->Next)
            {
                if (!addressInfo->Address.lpSockaddr || addressInfo->Address.lpSockaddr->sa_family != AF_INET /* IP v4 */)
                    continue;

                auto ipv4AddrInfo = reinterpret_cast<in_addr*>(addressInfo->Address.lpSockaddr);
                                                     ^^^^????
            }
        }
    }

给定一个 SOCKADDR*,查看其 sa_family 字段以确定地址类型。

  • 对于 AF_INET 地址,将 SOCKADDR* 类型转换为 SOCKADDR_IN*,然后您可以访问其 sin_addr 字段。

  • 对于 AF_INET6 地址,将 SOCKADDR* 类型转换为 SOCKADDR_IN6* 然后您可以访问它的 sin6_addr 字段。

std::vector<BYTE> buffer(defaultBufferSize);
auto pAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buffer.data());
ULONG outBufLen = defaultBufferSize;

constexpr ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
auto result = GetAdaptersAddresses(AF_INET /* Only IP v4 since no cameras use v6 yet */, flags, nullptr, pAddresses, &outBufLen);

uint32_t ipV4Address = 0;

// Iterating over the returned adapter info structures
for (auto currentInterfaceInfo = pAddresses; currentInterfaceInfo != nullptr; currentInterfaceInfo = currentInterfaceInfo->Next)
{
    if (currentInterfaceInfo->IfType != IF_TYPE_IEEE80211 || currentInterfaceInfo->Ipv4Enabled != 1 || currentInterfaceInfo->ReceiveOnly != 0)
        continue;

    for (auto addressInfo = currentInterfaceInfo->FirstUnicastAddress; addressInfo != nullptr; addressInfo = addressInfo->Next)
    {
        if (!addressInfo->Address.lpSockaddr || addressInfo->Address.lpSockaddr->sa_family != AF_INET /* IP v4 */)
            continue;

        auto ipv4AddrInfo = reinterpret_cast<sockaddr_in*>(addressInfo->Address.lpSockaddr);
        // use ipv4AddrInfo->sin_addr as needed...
    }
}