2015-02-16 2 views
1

Я разрабатываю приложение на основе C++ ASIO. Ссылаясь на Chat ServerC++ ASIO: обработчик async_accept() выдает исключение, когда сервер уничтожает

Класса Моего сервера:

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 ошибку потому что существующее по умолчанию прослушивания сеанса активно. И, возвращаясь с 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 destructionAsked Here

Как решить эту проблему и обеспечить чистый выход, когда ~CServer() называется.

+0

Почему вы уничтожаете объект 'CServer', если он все еще прослушивает входящие соединения? –

+0

Существует несколько 'CServer', поэтому, когда выходит из области действия' handle_accept() 'error, генерируется. Это также происходит, если я вызываю 'acceptor_.close()' и возвращаясь из 'handle_accept' - генерируется исключение. Как обеспечить чистое уничтожение «CServer Class» –

+0

в целом, вы гарантируете, что время жизни объекта CServer продолжается до тех пор, пока оно выполняет работу, например, при прослушивании входящих соединений. Обычно это делается путем наследования от 'enable_shared_from_this', некоторые из примеров Asio используют эту концепцию. –

ответ

3

Я предлагаю взглянуть на различные 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)); 

Но вы можете закрыть вниз явно от метода остановки, как:

Если вам нужно больше советов о том, как подключить, что мы должны увидеть остальную часть вашего кода ASIO.

+0

Я попробовал ваше предложение, но все же застрял в одном и том же месте, чтобы лучше понять проблему. Я упростил свое приложение и задал здесь вопрос http://stackoverflow.com/questions/28564029/asio-chat-session-class-throws- exception-on-destroy-c-asio Не могли бы вы посмотреть? –

+0

http://stackoverflow.com/questions/28607788/destroying-server-instance-asio-c Можете ли вы посмотреть @softwariness –

Смежные вопросы