Get Local IP-Address using Boost.Asio

后端 未结 5 750
悲&欢浪女
悲&欢浪女 2020-12-05 02:20

I\'m currently searching for a portable way of getting the local IP-addresses. Because I\'m using Boost anyway I thought it would be a good idea to use Boost.Asio for this t

5条回答
  •  情话喂你
    2020-12-05 03:16

    Cross platform, but only because of the #ifdef _WIN32 … #else:

    boost::asio::ip::address_v6 sinaddr_to_asio(sockaddr_in6 *addr) {
        boost::asio::ip::address_v6::bytes_type buf;
        memcpy(buf.data(), addr->sin6_addr.s6_addr, sizeof(addr->sin6_addr));
        return boost::asio::ip::make_address_v6(buf, addr->sin6_scope_id);
    }
    
    #if defined(_WIN32)
    #undef UNICODE
    #include 
    // Headers that need to be included after winsock2.h:
    #include 
    #include 
    
    typedef IP_ADAPTER_UNICAST_ADDRESS_LH Addr;
    typedef IP_ADAPTER_ADDRESSES *AddrList;
    
    std::vector get_local_interfaces() {
        // It's a windows machine, we assume it has 512KB free memory
        DWORD outBufLen = 1 << 19;
        AddrList ifaddrs = (AddrList) new char[outBufLen];
    
        std::vector res;
    
        ULONG err = GetAdaptersAddresses(AF_UNSPEC,
            GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, ifaddrs,
            &outBufLen);
    
        if (err == NO_ERROR) {
            for (AddrList addr = ifaddrs; addr != 0; addr = addr->Next) {
                if (addr->OperStatus != IfOperStatusUp) continue;
                // if (addr->NoMulticast) continue;
    
                // Find the first IPv4 address
                if (addr->Ipv4Enabled) {
                    for (Addr *uaddr = addr->FirstUnicastAddress; uaddr != 0; uaddr = uaddr->Next) {
                        if (uaddr->Address.lpSockaddr->sa_family != AF_INET) continue;
                        res.push_back(boost::asio::ip::make_address_v4(ntohl(reinterpret_cast(addr->ifa_addr)->sin_addr.s_addr)));
                    }
                }
    
                if (addr->Ipv6Enabled) {
                    for (Addr *uaddr = addr->FirstUnicastAddress; uaddr != 0; uaddr = uaddr->Next) {
                        if (uaddr->Address.lpSockaddr->sa_family != AF_INET6) continue;
                        res.push_back(sinaddr_to_asio(reinterpret_cast(addr->ifa_addr)));
                    }
                }
            }
        } else {
    
        }
        delete[]((char *)ifaddrs);
        return res;
    }
    #elif defined(__APPLE__) || defined(__linux__)
    #include 
    #include 
    #include 
    #include 
    
    std::vector get_local_interfaces() {
        std::vector res;
        ifaddrs *ifs;
        if (getifaddrs(&ifs)) {
            return res;
        }
        for (auto addr = ifs; addr != nullptr; addr = addr->ifa_next) {
            // No address? Skip.
            if (addr->ifa_addr == nullptr) continue;
    
            // Interface isn't active? Skip.
            if (!(addr->ifa_flags & IFF_UP)) continue;
    
            if(addr->ifa_addr->sa_family == AF_INET) {
                res.push_back(boost::asio::ip::make_address_v4(ntohl(
                    reinterpret_cast(addr->ifa_addr)->sin_addr.s_addr)));
            } else if(addr->ifa_addr->sa_family == AF_INET6) {
                res.push_back(sinaddr_to_asio(reinterpret_cast(addr->ifa_addr)));
            } else continue;
        }
        freeifaddrs(ifs);
        return res;
    }
    #else
    #error "..."
    #endif
    

提交回复
热议问题