Get Local IP-Address using Boost.Asio

后端 未结 5 741
悲&欢浪女
悲&欢浪女 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 02:56

    Here's a trick I learned from python network programming (google) to figure out my machine's ip address. This only works if you have an internet connection and can connect to google.com and does give me my home machine's 192.168.x.x private address.

    try {
        boost::asio::io_service netService;
        udp::resolver   resolver(netService);
        udp::resolver::query query(udp::v4(), "google.com", "");
        udp::resolver::iterator endpoints = resolver.resolve(query);
        udp::endpoint ep = *endpoints;
        udp::socket socket(netService);
        socket.connect(ep);
        boost::asio::ip::address addr = socket.local_endpoint().address();
        std::cout << "My IP according to google is: " << addr.to_string() << std::endl;
     } catch (std::exception& e){
        std::cerr << "Could not deal with socket. Exception: " << e.what() << std::endl;
    
     }
    
    0 讨论(0)
  • 2020-12-05 02:56

    If you edit your /etc/hosts file (this is *nix only, might work for windows too... I'm not sure) you can correct this issue.

    Inside the hosts file you'll find something like: (this is Ubuntu, note the 1.1)

    127.0.0.1 localhost
    127.0.1.1 yourPcName.yourNetwork.tld

    if you change this file to

    127.0.0.1 localhost
    127.0.1.1 yourPcName.yourNetwork.tld
    your.real.ip.here yourPcName

    then the hostname should resolve properly.

    One method of testing proper resolution is with the "hostname -i" command which should print your ip address incorrectly before you change hosts, and then correctly afterwards.

    Of course this is terrible solution for dynamic IPs... eh.

    0 讨论(0)
  • 2020-12-05 02:58

    You can find "your" address with the code you posted. BUT... it gets complicated. There may be multiple NICs, there may be LAN and WAN addresses, wired and wireless, loopback... On my desktop i had one NIC but two ips here from two diff DHCP servers on my lan...

    I found it was better to let the user provide the IP to bind to as a command line parameter. And yes, that's a portable solution! :-)

    0 讨论(0)
  • 2020-12-05 03:02

    Assuming you have one network card / one local ip address:

    #include <boost/asio.hpp>
    namespace ip = boost::asio::ip;
    
    std::string getAddress()
    {
        boost::asio::io_service ioService;
        ip::tcp::resolver resolver(ioService);
    
        return resolver.resolve(ip::host_name(), "")->endpoint().address().to_string();
    }
    
    0 讨论(0)
  • 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 <winsock2.h>
    // Headers that need to be included after winsock2.h:
    #include <iphlpapi.h>
    #include <ws2ipdef.h>
    
    typedef IP_ADAPTER_UNICAST_ADDRESS_LH Addr;
    typedef IP_ADAPTER_ADDRESSES *AddrList;
    
    std::vector<boost::asio::ip::address> 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<boost::asio::ip::address> 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<sockaddr_in *>(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<sockaddr_in6 *>(addr->ifa_addr)));
                    }
                }
            }
        } else {
    
        }
        delete[]((char *)ifaddrs);
        return res;
    }
    #elif defined(__APPLE__) || defined(__linux__)
    #include <arpa/inet.h>
    #include <ifaddrs.h>
    #include <net/if.h>
    #include <sys/types.h>
    
    std::vector<boost::asio::ip::address> get_local_interfaces() {
        std::vector<boost::asio::ip::address> 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<sockaddr_in *>(addr->ifa_addr)->sin_addr.s_addr)));
            } else if(addr->ifa_addr->sa_family == AF_INET6) {
                res.push_back(sinaddr_to_asio(reinterpret_cast<sockaddr_in6 *>(addr->ifa_addr)));
            } else continue;
        }
        freeifaddrs(ifs);
        return res;
    }
    #else
    #error "..."
    #endif
    
    0 讨论(0)
提交回复
热议问题