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

发布于 2024-11-15 18:37:13 字数 1290 浏览 5 评论 0原文

我如何处理 control-C 事件或停止我的 boost::asio 服务器。我有一个 TCP & udp 组合服务器并希望能够在我按 ctrl-c 时干净地退出。我得到了未处理的 control-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;
}

How do I handle the control-C event or stop my boost::asio server. I have a tcp & udp combined server and would like to be able to exit cleanly when I press ctrl-c. I get a first chance exception for unhandled control-C. Here is my code

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

離殇 2024-11-22 18:37:13

从 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;
};

注意,最新 Ubuntu 的 boost 版本是 1.46 - 所以这是前沿(primo 2012)。

干杯,

迈克尔

As of boost 1.47 you can use signal_set from asio:

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;
};

Beware, boost versions of e.g. latest Ubuntu is 1.46 - so this is bleeding edge (primo 2012).

Cheers,

Michael

旧时浪漫 2024-11-22 18:37:13

C 标准库包含 (例如 参见此处),您可以使用它注册 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) { }

}

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

The C standard library contains <signal.h> (e.g. see here), with which you can register a signal handler for SIGINT (Ctrl-C). That should do the trick, supposing your platform supports signals.

You might also want to register a handler for SIGTERM to respond gracefully to being 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) { }

}

As suggested by Sam Miller, suppose your main loop is a single-threaded boost.asio loop with some m_io_service.run(). Then instead of the global flags you could (assuming m_io_service is visible) post a stop handler to the io service from within the signal handlers.

自在安然 2024-11-22 18:37:13

您可以使用 asio 中的 signal_set,如下所示

// stop on ctrlC signal

boost::asio::signal_set signals(
    io_service,
    SIGINT,
    SIGTERM );
signals.async_wait(
    boost::bind(
        &boost::asio::io_service::stop,
        &io_service));

文档在这里

You can use signal_set from asio, like this

// stop on ctrlC signal

boost::asio::signal_set signals(
    io_service,
    SIGINT,
    SIGTERM );
signals.async_wait(
    boost::bind(
        &boost::asio::io_service::stop,
        &io_service));

The docs are here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文