2011-06-15 17 views
5

Control-C olayını nasıl ele alırım veya boost :: asio sunucumu nasıl durdurabilirim. Bir tcp & udp birleşik sunucum var ve ctrl-c'ye bastığımda temiz bir şekilde çıkabilmek istiyorum. İşlenmemiş kontrol için ilk fırsat istisnası-C. Burada sigint (Ctrl-C) için bir sinyal işleyici kaydedebilirsiniz hangi ile benim kodBir boost tcp/udp sunucusunda control-c'nin nasıl işleneceği

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

olası yinelenen gibi, asio gelen signal_set kullanabilirsiniz ] (http://stackoverflow.com/questions/4639909/standard-way-to-perform-a-clean-shutdown-with-boost-asio) – CharlesB

cevap

4

C standart kütüphanesi <signal.h> (örn see here) içerir olduğunu. Platformun sinyalleri desteklediğini varsayarsak, bu hile yapmalıdır.

Ayrıca, SIGTERM için bir ele geçiriciyi öldürme (1) ed olarak incelikle yanıt vermek için kaydettirmek isteyebilirsiniz. Sam Miller tarafından önerildiği gibi

#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) { } 

} 

, ana döngü bazı m_io_service.run() ile tek iş parçacıklı boost.asio döngü olduğunu varsayalım. Sonra küresel bayraklar yerine ( m_io_service görülebilir) post sinyal işleyicilerinden io servisine bir durdurucu işleyicisi olabilir.

+0

Tam bir cevap olmak için Sinyal işleyicisinden 'io_service' olay döngüsünü nasıl durduracağınızı önerin. –

+0

Tamam, bu noktaya bir açıklama ekledim ve ana örneğe kaba bir bayrak tabanlı durma koşulu ekledim. OP'nin ASIO io servislerini ayrı iş parçacıklarında çalıştırmak istediği düşünüldüğünde, sanırım kendi ana döngüsüne sahip olacak. –

4

boost 1.47 itibariyle size asio gelen signal_set kullanabilirsiniz:

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

, ör boost sürümlerini dikkat son Ubuntu 1.46'dır - bu yüzden kanama kenarı (primo 2012).

Alkış,

Michael

+0

Bu yanıtla ilgili sorunlar. C: signal_set yapıcısının io_service için bir referansa ihtiyacı vardır. B: handle_stop imzası yanlış. – ravenspoint

0

Sen Boost.Asio ile temiz bir şekilde kapatmak için [standart yol bu

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

İlgili konular