как работать с control-c в boost tcp / udp server - PullRequest
6 голосов
/ 16 июня 2011

Как мне обработать событие 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;
}

Ответы [ 3 ]

5 голосов
/ 18 января 2012

Начиная с буста 1.47, вы можете использовать signal_set из 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;
};

Осторожно, буст-версии, например, последней Ubuntu, равны 1.46 - так что это передовой край (primo 2012).

Ура,

Майкл

4 голосов
/ 16 июня 2011

Стандартная библиотека 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) { }

}

Как предположил Сэм Миллер, предположим, что ваш основной цикл является однопоточным циклом boost.asio с некоторыми значениями m_io_service.run(). Тогда вместо глобальных флагов вы могли бы (при условии, что m_io_service виден) post обработчик остановки для службы io из обработчиков сигналов.

0 голосов
/ 05 октября 2017

Вы можете использовать signal_set из asio, как это

// 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));

Документы здесь

...