Boost :: Asio Async Failed To Record

I am porting an application that uses Boost :: Asio to the embedded system.

I have already cross-compiled binaries with the extension 1.57.0 for the board using its BSP. To test the operation of the libraries, I ran two examples of HTTP servers that use synchronized and asynchronous writing, respectively.

The Sync version is working fine; while Async failed to write. He returned an error "Operation canceled."

Can someone indicate where I should look? Thank.

/*
 * Boost::Asio async example
 */
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>

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

struct CHelloWorld_Service
{
        CHelloWorld_Service(io_service &iosev)
                :m_iosev(iosev),m_acceptor(iosev, tcp::endpoint(tcp::v4(), 1000))
        {}

        void start()
        {
                boost::shared_ptr<tcp::socket> psocket(new tcp::socket(m_iosev));
                m_acceptor.async_accept(*psocket,
                        boost::bind(&CHelloWorld_Service::accept_handler, this, psocket, _1));
        }

        void accept_handler(boost::shared_ptr<tcp::socket> psocket, error_code ec)
        {
                if(ec) return;
                start();
                std::cout << psocket->remote_endpoint().address() << std::endl;
                boost::shared_ptr<std::string> pstr(new std::string("hello async world!"));
                psocket->async_write_some(buffer(*pstr),
                        boost::bind(&CHelloWorld_Service::write_handler, this, pstr, _1, _2));
        }

        void write_handler(boost::shared_ptr<std::string> pstr, error_code ec,
                size_t bytes_transferred)
        {
                if(ec)
                std::cout<< "Failed to send! " << boost::system::system_error(ec).what() << std::endl;
                else
                std::cout<< *pstr << " has been sent" << std::endl;
        }

        private:
                io_service &m_iosev;
                ip::tcp::acceptor m_acceptor;
};

int main(int argc, char* argv[])
{
        io_service iosev;
        CHelloWorld_Service sev(iosev);
        sev.start();
        iosev.run();

        return 0;
}
+1
source share
1 answer

When async_write_someyou call, you forget to save the link to the socket instance.

socket, . , ec operation_aborted.

, socket , , enable_shared_from_this CSession.

shared_pointer magic:

:

void write_handler(
        boost::shared_ptr<std::string> pstr, 
        boost::shared_ptr<tcp::socket> /*keepalive!*/, 
        error_code ec, size_t bytes_transferred) 
{
    if(ec)
        std::cout<< "Failed to send! " << boost::system::system_error(ec).what() << "\n";
    else
        std::cout<< *pstr << " has been sent (" << bytes_transferred << " bytes transferred)\n";
}

:

    psocket->async_write_some(ba::buffer(*pstr),
            boost::bind(&CService::write_handler, this, pstr, psocket,
                ba::placeholders::error, ba::placeholders::bytes_transferred));

Live On Coliru

  • not using namespace
  • asio ( _1, _2)

g++ -std=c++11 -O2 -Wall -pedantic main.cpp -pthread -lboost_system -lboost_filesystem && ./a.out& while sleep .1; do nc 127.0.0.1 6767; done
127.0.0.1
hello async world!hello async world! has been sent (18 bytes transferred)
127.0.0.1
hello async world!hello async world! has been sent (18 bytes transferred)
127.0.0.1
hello async world!hello async world! has been sent (18 bytes transferred)
...

CSession (enable_shared_from_this)

, .

, , , :

struct CSession : boost::enable_shared_from_this<CSession> {
    CSession(ba::io_service &iosev)
        :m_iosev(iosev), m_sock(m_iosev)
    {}

    void do_response();

  private:
    void write_handler(error_code ec, size_t bytes_transferred);

    ba::io_service &m_iosev;
    tcp::socket m_sock;
    std::string response;
};

:

boost::bind(&CSession::write_handler,
     shared_from_this(), /* keep-alive! */
     ba::placeholders::error, ba::placeholders::bytes_transferred)

. CService, :

void start()
{
    auto session = boost::make_shared<CSession>(m_iosev);
    m_acceptor.async_accept(session->m_sock,
            boost::bind(&CService::accept_handler, this, session, ba::placeholders::error));
}

void accept_handler(boost::shared_ptr<CSession> session, error_code ec) {
    if(ec) {
        std::cerr << "Accept failed: " << ec.message() << "\n";
    } else {
        session->do_response();
        start();
    }
}

Live On Coliru

#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/enable_shared_from_this.hpp>

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

namespace HelloWorld {

    struct CSession : boost::enable_shared_from_this<CSession> {
        CSession(ba::io_service &iosev)
            :m_iosev(iosev), m_sock(m_iosev)
        {}

        void do_response() {
            response = "hello async world!\n";
            std::cout << m_sock.remote_endpoint().address() << std::endl;

            m_sock.async_write_some(ba::buffer(response),
                    boost::bind(&CSession::write_handler,
                        shared_from_this(), /* keep-alive! */
                        ba::placeholders::error, ba::placeholders::bytes_transferred));
        }

      private:

        void write_handler(error_code ec, size_t bytes_transferred) 
        {
            if(ec)
                std::cout<< "Failed to send! " << boost::system::system_error(ec).what() << "\n";
            else
                std::cout<< response << " has been sent (" << bytes_transferred << " bytes transferred)\n";
        }

        ba::io_service &m_iosev;

        friend class CService;
        tcp::socket m_sock;

        std::string response;
    };

    struct CService
    {
        CService(ba::io_service &iosev)
            :m_iosev(iosev),m_acceptor(iosev, tcp::endpoint(tcp::v4(), 6767))
        {}

        void start() {
            auto session = boost::make_shared<CSession>(m_iosev);
            m_acceptor.async_accept(session->m_sock,
                    boost::bind(&CService::accept_handler, this, session, ba::placeholders::error));
        }

        void accept_handler(boost::shared_ptr<CSession> session, error_code ec) {
            if(ec) {
                std::cerr << "Accept failed: " << ec.message() << "\n";
            } else {
                session->do_response();
                start();
            }
        }

      private:
        ba::io_service &m_iosev;
        tcp::acceptor m_acceptor;
    };
}

int main() {
    ba::io_service iosev;

    using namespace HelloWorld;

    CService sev(iosev);
    sev.start();
    iosev.run();
}

.

+2

All Articles