За основу был взят вот этот пример
http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/allocation/s...
исключение, составляет то, что там для socket создается отдельный класс Session. Я делаю вот так
void DeviceTower::start_accept()
{
boost::shared_ptr<boost::asio::ip::tcp::socket> socket(new boost::asio::ip::tcp::socket(io_service_));
uint64_t session_id = add_session(socket);
LOG("Create session %d", session_id);
acceptor_.async_accept(*(socket.get()),
boost::bind(&DeviceTower::handle_accept, this, session_id, socket, boost::asio::placeholders::error));
}
Т.е. я создаю сокет в обертке shared_ptr, кладу его в список активных (функция add_session), далее в обработчике
void DeviceTower::handle_accept(uint64_t id, boost::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::system::error_code& error)
{
LOG("enter");
if(error == boost::asio::error::operation_aborted)
{
LOG("Close acceptor on port [%d]", port_);
delete_session(id);
}
else if(error)
{
LOG_ERR("An error occurred when the client connected: %s", error.message().c_str());
delete_session(id);
}
else
{
start_accept();
boost::shared_ptr<boost::array<char, 1024> > buff(new boost::array<char, 1024>());
socket->async_read_some(boost::asio::buffer(*(buff.get())),
boost::bind(&DeviceTower::handle_read, this, id, socket, buff, boost::asio::placeholders::error));
}
}
Я выполняю асинхронное чтение async_read_some.
Вопрос вот в чем. Когда мне нужно остановить мое приложение, мне нужно закрыть все сокеты что бы прервать все асинхронные операции что в свою очередь отпусти io_service.run()
void DeviceTower::stop()
{
boost::system::error_code ec;
acceptor_.close(ec);
if(ec)
LOG_ERR("Device [%s] err occurred while close acceptor: ", name(), ec.message().c_str());
boost::mutex::scoped_lock lock(mtx_);
SessionsMap::iterator it = openSession_.begin();
for(; it != openSession_.end(); it++)
{
LOG("Call close for session %d", it->first);
ec.clear();
it->second->close(ec);
if(ec)
LOG_ERR("Error %s", ec.message().c_str());
}
while(!io_service_.stopped())
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
В документации Boost сказано что вызов close() на сокете приведет к тому что все зарегистрированные асинхронные операции, вызову свои коллбеки с ошибкой
boost::asio::error::operation_aborted
Для моего acceptor это происходит. Вызывается handle_accept с этой ошибкой. А вот для async_read_some не вызывается. И io_service.run() соответственно не отпускает управление.
Что я делаю не так? Я пробовал вызывать cancel, shutdown все безрезультатно :(.
Вызывать просто io_service.stop() я не хочу, потому что я не понимаю, что в этом случае случиться со всем зарегистрированными асинх. операциями.