如何在boost tcp/udp服务器中处理control-c

Gen*_*too 6 c++ boost-thread boost-asio

如何处理control-C事件或停止我的boost :: asio服务器.我有一个tcp&udp组合服务器,并希望能够在按ctrl-c时干净利落地退出.我得到了未处理控件-C的第一次机会异常.这是我的代码

void startTCP()
{
  http::syncServer::server serv( 2);

 // Set console control handler to allow server to be stopped.
 // console_ctrl_function = boost::bind(&http::syncServer::server::stop, &serv);
 //SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
 // Run the server until stopped.
 serv.run();
}


void startUDP()
{
  boost::asio::io_service io_service;
  http::syncServer::udp_server server(io_service);
 // console_ctrl_function = boost::bind(&http::syncServer::udp_server::stop, &server);
 // SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
 io_service.run();
}

int main(int argc, char* argv[])
{
  try
  {
     boost::shared_ptr<boost::thread> tcpThread( new boost::thread(startTCP));
     boost::shared_ptr<boost::thread> udpThread (new boost::thread(startUDP));

     /*console_ctrl_function = boost::bind(&http::syncServer::udp_server::stop, &server);
     SetConsoleCtrlHandler(console_ctrl_handler, FALSE);*/

    tcpThread->join();
    udpThread->join();
}
catch (std::exception& e)
{
   std::cerr << "exception: " << e.what() << "\n";
}

return 0;
}
Run Code Online (Sandbox Code Playgroud)

小智 5

从boost 1.47开始,你可以使用asio的signal_set:

class Server {
public:
  Server(...) {
    _signals.add(SIGINT);
    _signals.add(SIGTERM);
    _signals.async_wait(bind(&Server::handle_stop, this));

  }
  void handle_stop() {
    // do what you need to kill the Server - usually you just have to cancel all waits (incl deadline_timers), which will make the io_service exit gracefully
  }
private:
  boost::asio::signal_set _signals;
};
Run Code Online (Sandbox Code Playgroud)

当心,最新的Ubuntu的升级版本是1.46 - 所以这是最前沿的(primo 2012).

干杯,

迈克尔


Ker*_* SB 4

C 标准库包含<signal.h>(例如参见此处),您可以使用它注册 SIGINT (Ctrl-C) 的信号处理程序。假设您的平台支持信号,这应该可以解决问题。

您可能还想为 SIGTERM 注册一个处理程序,以优雅地响应被kill(1)ed。

#include <signal.h> // or <csignal> in C++

void ctrlchandler(int) { /*...*/ WE_MUST_STOP = 1; }
void killhandler(int) { /*...*/ WE_MUST_STOP = 2; }

int WE_MUST_STOP = 0;

int main() {
  signal(SIGINT, ctrlchandler);
  signal(SIGTERM, killhandler);
  /* ... */

  // e.g. main loop like this:
  while(pump_loop() && 0 == WE_MUST_STOP) { }

}
Run Code Online (Sandbox Code Playgroud)

正如 Sam Miller 所建议的,假设您的主循环是一个单线程 boost.asio 循环,其中包含一些m_io_service.run(). 然后,您可以(假设m_io_service可见)从信号处理程序内将停止处理程序发布到 io 服务,而不是全局标志。