ipv4 и ipv6 с любого действительного адреса

Я пытаюсь получить адреса ipv4 и ipv6 с любого строкового адреса, будь то по ipv4, ipv6 или DNS-адресу.

Для этого я могу создать свою собственную функцию, но я пытаюсь воспользоваться советами экспертов и использовать встроенные возможности.

Есть ли способ ввода адреса string любого формата, и возвращены ли буст-адреса ipv4 и ipv6?

2 ответа

Решение

Получение адреса из DNS-имени включает в себя... запрос к серверу имен (DNS!). Если вы хотите перечислить результаты, используйте распознаватель в asio:

Простой пример:

#include <boost/asio.hpp>
#include <boost/function_output_iterator.hpp>
#include <set>

using boost::asio::ip::address;

std::set<address> unique_endpoints(std::string const& ip)
{
    using resolver = boost::asio::ip::tcp::resolver;
    boost::asio::io_service ios; // TODO use existing service / resolver
    resolver r(ios);

    std::set<address> unique;
    for (auto it = r.resolve({ip, ""}); it != resolver::iterator {}; ++it)
    {
        //std::cout << "Resolved: " << it->host_name() << " -> " << it->endpoint() << " " << it->service_name() << "\n";
        address a = it->endpoint().address();
        if (a.is_v4())
            unique.insert(boost::asio::ip::address_v6::v4_mapped(a.to_v4()));
        else
            unique.insert(a);
    }

    return unique;
}

template <typename S>
bool endpoints_overlap(S const& a, S const& b)
{
    bool matching_found = false;

    std::set_intersection(
            a.begin(), a.end(), b.begin(), b.end(),
            boost::make_function_output_iterator([&](address const&) { matching_found = true; }));

    return matching_found;
}

int main()
{
    auto h = unique_endpoints("bbs2.fritz.box");
    auto a = unique_endpoints("192.168.2.111");
    auto b = unique_endpoints("::ffff:192.168.2.111");
    auto c = unique_endpoints("::ffff:c0a8:026f");

    assert(endpoints_overlap(a, b));
    assert(endpoints_overlap(a, c));
    assert(endpoints_overlap(b, c));

    assert(endpoints_overlap(h, a));
    assert(endpoints_overlap(h, b));
    assert(endpoints_overlap(h, c));
}

Обратите внимание, что этот тест решит, что конечные точки перекрываются, когда один из ответов DNS совпадает. Это может не всегда быть правдой в настройках кластера (нет эксперта), и вы также можете определить широковещательные адреса перед использованием этого алгоритма (не проверено).

Также обратите внимание, что я не думаю, что есть способ обнаружить эквивалентность реальных хостов (то есть, если у хоста есть несколько физических / логических сетевых карт, они будут отображаться как отдельные серверы на транспортном уровне).

Наконец, в реальном приложении вы захотите выполнить разрешение асинхронно (используйте async_resolve)

boost::ip::address обеспечивает этот тип функциональности.

Вы можете создать адрес из строки любого формата (десятичного для ipv4 или шестнадцатеричного для ipv6), используя функцию from_string:

boost::ip::address address( boost::ip::address::from_string( myIpAddress ) );

Тогда вы сможете вернуть IP-адрес v4 или v6:

boost::asio::ip::address_v4 ipv4 = address.to_v4();
boost::asio::ip::address_v6 ipv6 = address.to_v6();
Другие вопросы по тегам