ASIO getting a tcp endpoint directly from an asynchronous resolve

前端 未结 1 802
鱼传尺愫
鱼传尺愫 2021-01-25 02:32

I\'m looking to use the ASIO standalone library (not Boost ASIO), I am trying to set up a client to connect to a server on a specific port.

I saw in the porthopper examp

相关标签:
1条回答
  • 2021-01-25 02:32

    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

    0 讨论(0)
提交回复
热议问题