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> ,
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(),
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(),
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();
}
.