C++ ASIO : async_accept() handler throws exception when server destroys

标签 c++ boost-asio

我正在开发一个基于 C++ ASIO 的应用程序。引用Chat Server

我的服务器类:

class CServer  {

public:

    CServer(asio::io_service& io_service, const std::string serIdentity, std::string IP, const std::string port);
    ~CServer();

    void listen();
    void handle_accept(sessionPtr newSession, const asio::error_code& error);
private:

    tcp::acceptor acceptor_; // only in the listener
    asio::io_service& io_;
    CSerSessionsManager mng_;

};

void CServer::listen()
{
sessionPtr newSession = std::make_shared<channel::CSerSession>(io_, mng_, serIdentifier_, ip_, port_);

    acceptor_.async_accept(newSession->socket(), std::bind(&CServer::handle_accept, this, newSession,
                std::placeholders::_1));
} 

    void CServer::handle_accept(sessionPtr newSession, const asio::error_code& error)
{
    if (!error)
    {
        //Do Something
        listen();
    }
    else
    {
        DEBUG_MSG("Listen_Error");
        //Returning from here throws Exception
    }
    
}

当我的 CServer Object调用 ~CServer() 后销毁设置Handle Accept错误,因为现有的默认监听 session 处于事件状态。从 handle_accept() 返回时它抛出异常。

Unhandled exception at 0x74E8C42D in channel.exe: Microsoft C++ exception: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::system_error> > at memory location 0x023EF3EC.

下面是调用栈:

>   channel.exe!boost::throw_exception<std::system_error>(const std::system_error & e) Line 69  C++
    channel.exe!asio::detail::do_throw_error(const std::error_code & err) Line 32   C++
    channel.exe!asio::detail::throw_error(const std::error_code & err) Line 34  C++
    channel.exe!asio::io_service::run() Line 59 C++
    channel.exe!boost::_mfi::mf0<unsigned int,asio::io_service>::operator()(asio::io_service * p) Line 49   C++
    channel.exe!boost::_bi::list1<boost::_bi::value<asio::io_service *> >::operator()<unsigned int,boost::_mfi::mf0<unsigned int,asio::io_service>,boost::_bi::list0>(boost::_bi::type<unsigned int> __formal, boost::_mfi::mf0<unsigned int,asio::io_service> & f, boost::_bi::list0 & a, long __formal) Line 244  C++
    channel.exe!boost::_bi::bind_t<unsigned int,boost::_mfi::mf0<unsigned int,asio::io_service>,boost::_bi::list1<boost::_bi::value<asio::io_service *> > >::operator()() Line 21   C++
    channel.exe!asio::detail::win_thread::func<boost::_bi::bind_t<unsigned int,boost::_mfi::mf0<unsigned int,asio::io_service>,boost::_bi::list1<boost::_bi::value<asio::io_service *> > > >::run() Line 116    C++
    channel.exe!asio::detail::win_thread_function(void * arg) Line 109  C++

我对 session class destruction 也有类似的问题Asked Here

我该如何解决这个问题并确保在 ~CServer() 时干净退出?被称为。

最佳答案

我建议查看各种 HTTP Server Examples对于 Boost ASIO,因为它们比聊天示例更完整。

一种用于关闭服务器对象的模式是使用 handle_stop 方法来关闭接受器并关闭连接,例如以下来自上面链接的单线程 HTTP 服务器示例:

void server::handle_stop()
{
  // The server is stopped by cancelling all outstanding asynchronous
  // operations. Once all operations have finished the io_service::run() call
  // will exit.
  acceptor_.close();
  connection_manager_.stop_all();
}

在 Boost 示例中,这是由 Ctrl-C 处理程序调用的:

  // Register to handle the signals that indicate when the server should exit.
  // It is safe to register for the same signal multiple times in a program,
  // provided all registration for the specified signal is made through Asio.
  signals_.add(SIGINT);
  signals_.add(SIGTERM);
#if defined(SIGQUIT)
  signals_.add(SIGQUIT);
#endif // defined(SIGQUIT)
  signals_.async_wait(boost::bind(&server::handle_stop, this));

但您可能希望通过停止方法显式关闭,例如:

void server::stop()
{
    io_service_.post(boost::bind(&server::handle_stop, this));
}

如果您需要更多关于如何连接它的建议,我们需要查看您的其余 ASIO 代码。

关于C++ ASIO : async_accept() handler throws exception when server destroys,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28547419/

相关文章:

c++ - 由于英国夏令时, boost 计时器停止工作

c++ - extern的使用和防止重复定义

c++ - 比较和交换与测试和设置

c++ - 静态函数中的命名空间

c++ - 亚信 : Is there an automatically resizable buffer for receiving input?

android - 官方 "Boost library"支持安卓和iOS?

c++ - 无法在 C++ 类中分配 cv::Mat 对象

C++ 使用 toString() 方法有什么问题

c++ - 如何使用 boost::asio::serial_port 支持硬件流控制?

c++ - 在读取之前检查 boost::asio 套接字上的数据?或者我应该使用 async_read()?