ASIO getting a tcp endpoint directly from an asynchronous resolve

本秂侑毒 提交于 2019-12-02 03:57:10

Oh, but

tcp::endpoint remote_endpoint = *resolver.resolve(query);

deals with the iterator very much! It uses it to dereference. Note that cute star? It's the pointer indirection operator.

As for your call:

resolver.async_resolve(query,
            [this](const tcp::endpoint srvEndpoint, std::error_code error)
            {
                IOService->post(
                    [this, error, srvEndpoint]
                    {
                         handle_resolve_handler(error, srvEndpoint);
                    });
            });

That does not satisfy the completion handler requirements. Indeed, trying to compile it with Boost Asio² gives a slew of errors: Live On Coliru:

main.cpp:12:14:   required from here
/usr/local/include/boost/asio/ip/basic_resolver.hpp:163:5: error: static assertion failed: ResolveHandler type requirements not met
     BOOST_ASIO_RESOLVE_HANDLER_CHECK(
     ^
/usr/local/include/boost/asio/ip/basic_resolver.hpp:163:5: error: no match for call to '(Demo::doResolve()::<lambda(boost::asio::ip::tcp::endpoint, boost::system::error_code)>) (const boost::system::error_code&, const boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>&)'
     BOOST_ASIO_RESOLVE_HANDLER_CHECK(

The docs say:

Lo and behold, there's your iterator again! This is by no means an accident. The design of the library is such that async calls will always return the same data regardless of the chosen interface.¹

Cobbling it together: Live On Coliru

#include <boost/asio.hpp>
#include <iostream>

namespace asio = boost::asio;
using boost::system::error_code;
using asio::ip::tcp;

struct Demo {
    Demo(asio::io_service& svc) : _svc(svc) {}
    void doResolve() {
        resolver.async_resolve(query, [this](error_code error, tcp::resolver::iterator it) {
                tcp::endpoint ep = error? tcp::endpoint{} : *it;
                _svc.post([this, error, ep] { handle_resolve_handler(error, ep); });
            });
    }

  private:
    asio::io_service& _svc;
    tcp::resolver resolver     {_svc};
    tcp::resolver::query query {"www.google.com", "https"};

    void handle_resolve_handler(error_code ec, tcp::endpoint srvEndpoint) {
        std::cout << "handle_resolve_handler: " << ec.message() << " " << srvEndpoint << "\n";
    }
};

int main() {
    asio::io_service svc;
    Demo x(svc);
    x.doResolve();

    svc.run();
}

Prints³:

handle_resolve_handler: Success 216.58.213.196:443

¹ cf. the difference when using coroutines (yield or yield[ec]), asio::use_future etc.: How to set error_code to asio::yield_context

² basically s/boost::system::error_code/std::error_code/

³ On systems with network access

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!