C++ boost::asio io_服务不';停止后不返回()

C++ boost::asio io_服务不';停止后不返回(),c++,boost,boost-asio,C++,Boost,Boost Asio,我正在开发一个应用程序,它使用boost::asio在不同端口上侦听TCP和UDP数据包。我通过使用与asio教程示例中类似的服务器类来实现这一点,并将它们全部指向一个io_服务 因此,总体而言,我的主要功能(win32控制台应用程序)如下所示: int main(int argc, char* argv[]) { //some initializations here try { asio::io_service io_service;

我正在开发一个应用程序,它使用boost::asio在不同端口上侦听TCP和UDP数据包。我通过使用与asio教程示例中类似的服务器类来实现这一点,并将它们全部指向一个io_服务

因此,总体而言,我的主要功能(win32控制台应用程序)如下所示:

int main(int argc, char* argv[])
{
    //some initializations here

    try
    {
        asio::io_service io_service;
        TcpServer ServerTCP_1(io_service, /*port number here*/);
        TcpServer ServerTCP_2(io_service, /*port number here*/);
        UdpServer ServerUDP(io_service, /*port number here*/);

        io_service.run();
    }
    catch(std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    //cleanup code here

    return 0;
}
现在,由于我有3个不同的服务器对象,他应该关闭它们的所有接收器,让
io_服务
不工作,这会再次导致
io_服务
run()
调用返回,这会使程序进入主函数中的清理代码,对吗? 除此之外,
printf
调用还应该执行3次,或者

首先,
io\u服务
不会返回,清理代码永远不会到达。 其次,控制台中最多只显示一个printf调用

第三,通过调试,我发现当我退出程序时,
handle\u stop()

另一件可能值得一提的事情是,程序在关闭后不会返回0,而是返回0(线程的数量不同):


因此,我想知道为什么会发生这种情况,我如何修复它,以及如何正确地获取清理代码?

由于
io\u服务中总是有工作,因此
io\u服务将永远不会返回。调用时,
接受器的异步接受操作将立即取消。这些已取消操作的处理程序将被传递
boost::asio::error::operation\u aborted
错误

在当前代码中,问题是始终启动新的异步接受操作的结果,即使
接受程序
已关闭。因此,工作总是被添加到
io\u服务中

void start_accept(){
  // If the acceptor is closed, handle_accept will be ready to run with an
  // error.
  acceptor_.async_accept(...,  handle_accept);
}

void handle_accept(const system::error_code& error){
  if(!error)
  {
    connection->start();
  }

  // Always starts a new async accept operation, even if the acceptor
  // has closed.
  start_accept();
}
void handle_stop(){
  acceptor_.close();
}
Boost.Asio示例通过检查
handle\u accept
调用中是否关闭了
acceptor\u
来防止这种情况发生。如果
acceptor\u
不再打开,则处理程序将提前返回,而不会向
io\u服务添加更多工作

void start_accept(){
  // If the acceptor is closed, handle_accept will be ready to run with an
  // error.
  acceptor_.async_accept(...,  handle_accept);
}

void handle_accept(const system::error_code& error){
  if(!error)
  {
    connection->start();
  }

  // Always starts a new async accept operation, even if the acceptor
  // has closed.
  start_accept();
}
void handle_stop(){
  acceptor_.close();
}
以下是示例中的相关片段:


为了澄清,您是否如问题标题中所建议的那样致电?此外,可能值得发布更多代码,因为问题似乎在其他地方。我以前在handle_stop中使用过它,但1)它也没有效果(io_服务没有返回),2)我将其更改为acceptor_u.close(),因为在一些boost示例中也使用了它。还有,你会推荐什么代码,或者你对什么代码感兴趣,我不确定如果我用我所有的代码垃圾发布这个主题会有什么好处;)服务器析构函数、接受调用和处理程序可以提供一些细节。如果未返回
io\u service::run()
,则不会调用每个
信号集的处理程序,并且catch不会打印异常,然后它通常表示某个地方发生了阻塞调用。我更新了我的帖子,实际上我没有自定义析构函数,因为我在boost示例中也没有看到任何析构函数。这听起来不错,但即使在这些更改之后,io_服务仍然没有返回。当我尝试调试调用handle_stop()时发生的事情时,整个程序在调用acceptor_u.close()或printf()后退出(与我上面描述的问题相同)。出于测试目的,我只使用了一个服务器对象,但问题仍然存在,即使没有发生任何事情(没有连接客户端)。据我所知,在调用acceptor_979;.close()时,也不会调用处理程序。@user2047610:听起来好像在调用未发布的代码中未定义的行为。基于这些调用,我建议验证
TcpConnection
实例是否比它绑定到的所有处理程序都长。确保它是从
enable\u shared\u from\u this
公开继承的,并且实例是通过
boost::bind
而不是
shared\u this
绑定到具有
shared\u from\u this()的处理程序的。但是当我这样做时,他抛出了一个异常“tr1::bad\u弱\u ptr”,可能是因为使用了\u this()的shared\u在TcpServer构造函数中设置的信号\u的异步调用中,如何解决此问题?@user2047610:
shared\u from\u this()
不能在调用它的类的构造函数中使用。例如,不应从
TcpConnection
的构造函数中调用this()
中的
shared\u。考虑一下如何在HTTP Server 1类中使用<代码> SydRyFasBy()/<代码>。好吧,出于好奇,我花了时间编译HTTP示例1和3(从示例中取出代码1:1),同样的问题发生了!io_服务不返回,并且在退出时返回相同的代码(-1073741510(0xc000013a))。这让我想到一个问题,这是否可能是一个更深层次的问题?我正在使用64位Windows 7,并使用Visual Studio 2010进行编译和调试。
void start_accept(){
  // If the acceptor is closed, handle_accept will be ready to run with an
  // error.
  acceptor_.async_accept(...,  handle_accept);
}

void handle_accept(const system::error_code& error){
  if(!error)
  {
    connection->start();
  }

  // Always starts a new async accept operation, even if the acceptor
  // has closed.
  start_accept();
}
void handle_stop(){
  acceptor_.close();
}
void server::handle_accept(const boost::system::error_code& e)
{
  // Check whether the server was stopped by a signal before this completion
  // handler had a chance to run.
  if (!acceptor_.is_open())
  {
    return;
  }

  if (!e)
  {
    connection_manager_.start(new_connection_);
  }

  start_accept();
}