本文介绍了C ++ ASIO:async_accept()处理程序在服务器销毁时抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我正在开发一个基于C ++ ASIO的应用程序。参考聊天服务器 我的服务器类别: 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) { //做某事 listen(); } else { DEBUG_MSG(Listen_Error); //从这里返回throws异常} } $ b b 当我的 CServer Object 销毁时,调用〜CServer() $ c>处理接受错误,因为现有默认侦听会话处于活动状态。从 handle_accept()返回时,它会抛出异常。 0x74E8C42D处的未处理异常channel.exe:Microsoft C ++异常:boost :: exception_detail :: clone_impl< boost :: exception_detail :: error_info_injector< std :: system_error> > > > 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&错误)第32行C ++ channel.exe!asio :: detail :: throw_error(const std :: error_code& err)第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)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)行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()()第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 ++ 我有类似的问题与会话类销毁 $ b $ b 如何解决这个问题,并且在调用〜CServer()时确保干净退出。解决方案我建议您查看各种用于Boost ASIO的HTTP Server示例,因为它们比聊天示例更完整。 用于关闭服务器对象的工作是具有关闭接受器并关闭连接的 handle_stop 方法,例如以下来自上面链接的单线程HTTP服务器示例: void server :: handle_stop() { //通过取消所有未完成的异步 //操作来停止服务器。一旦所有操作完成io_service :: run()调用 //将退出。 acceptor_.close(); connection_manager_.stop_all();在Boost示例中,这是由Ctrl-C处理程序调用的: //注册以处理指示服务器应何时退出的信号。 //在程序中多次注册相同的信号是安全的, //提供的所有注册的指定信号是通过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 , 这个)); } 如果您需要更多有关如何挂钩的建议,以查看其余的ASIO代码。 I am developing a C++ ASIO based application. Referring to Chat ServerMy Server Class: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 }}When my CServer Object destroys, after calling ~CServer() It sets Handle Accept error because an existing default listening session is active. And while returning from handle_accept() it throws exception.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.below is the call stack:> 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++I had similar issue with session class destruction Asked HereHow do I resolve this and ensure clean exit when ~CServer() is called. 解决方案 I'd suggest having a look at the various HTTP Server Examples for Boost ASIO as they are more complete than the chat example.One pattern that works for shutdown of a server object is to have a handle_stop method that closes the acceptor and shuts down the connections, e.g. the following from the single-threaded HTTP Server Example linked above: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();}In the Boost example, this is called by a Ctrl-C handler: // 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));But you might want to shut-down explicitly from a stop method, like:void server::stop(){ io_service_.post(boost::bind(&server::handle_stop, this));}If you need more advice on how to hook that in, we'll need to see the rest of your ASIO code. 这篇关于C ++ ASIO:async_accept()处理程序在服务器销毁时抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-23 05:13