gSoap: как изящно закрыть приложение веб-сервиса?

Я использую gSoap для написания веб-сервиса. Он работает как консольное приложение. Во всех примерах gSoap я вижу, что запросы отправляются в бесконечном цикле, подобно for(;;;) даже в многопоточной версии.

Но как я могу заставить свою веб-службу корректно завершать работу, когда, скажем, пользователь нажимает пробел на консоли?

Предпочтительно:

  1. прекратить прием новых подключений;
  2. обслуживать существующие;
  3. Выйти из приложения

person Vladislav Rastrusny    schedule 08.03.2011    source источник
comment
вы ищете логику или исходный код?   -  person fazo    schedule 25.03.2011
comment
Все, что поможет мне понять, как это сделать. Код предпочтительнее, но я не дурак, и я думаю, что мне хватит пары слов на эту тему ;) Сейчас я просто выхожу из цикла kbhit()=true и жду несколько секунд, пока просит закончить. Но это не надежно. Что, если какой-то поток займет больше времени?   -  person Vladislav Rastrusny    schedule 25.03.2011


Ответы (3)


Раздел 7.2.4 Создание многопоточной автономной службы в документации есть пример кода для написания цикла принятия. Вам нужно написать свой собственный цикл приема и добавить обработку сигналов, чтобы он реагировал на Ctrl-C.

  1. прекратить прием новых подключений:

    Выйдите из цикла, чтобы прекратить вызов accept.

  2. Обслуживать существующие:

    Потоки должны информировать вас о завершении, чтобы вы могли выйти, когда количество активных клиентов равно нулю. (у boost::thead_group есть функция join_all, которая делает именно это.)

  3. Выход из приложения:

person Eddy Pronk    schedule 25.03.2011
comment
К сожалению, решение Эдди мне не подходит. soap_accept, похоже, не выходит по сигналу. Я добавил select в soap.master перед вызовом soap_accept. Когда сигнал получен, выбор прервется с помощью EINTR, который я затем смогу подобрать и использовать для выхода из процесса. Если select возвращает успех, я просто вызываю soap_accept, как и раньше. ХТН. - person user2461592; 20.06.2013

Единственное решение, которое я придумал до сих пор, это использование тайм-аутов soap->recv_timeout = 20; мыло->send_timeout = 20; мыло->connect_timeout = 5; мыло->accept_timeout = 5; Затем все блокирующие функции периодически возвращаются. Но это не идеально для меня, потому что я хочу иметь возможность быстро завершить приложение, даже если есть текущая передача, но в то же время не хочу ставить под угрозу надежность при медленном/ненадежном соединении (это встроенный устройство, подключенное через GPRS).

person ilya    schedule 08.05.2014

Что вам нужно сделать, так это зарегистрировать обработчик сигнала, поэтому, когда вы завершаете свое приложение с помощью Ctrl + C, оно вызывает зарегистрированную вами функцию, где вы можете изящно завершить работу.

e.g

class gsoap_test {

public:
   void start() {
     running_ = true;
     while(running_) {
       //gsoap threads
     }
     //stop and cleanup
   }


   void stop() {
        running_ = false;
   }
 private:
      bool running_;
};

 //global variable 
 gsoap_test gsoap;


void sighandler(int sig)
{
    std::cout<< "Signal caught..." << std::endl;

    //Stop gracefully here
    gsoap.stop();
    exit(0);

}

int main(int argc, char** argv) {

  //register signal
   signal(SIGABRT, &sighandler);
   signal(SIGTERM, &sighandler);
   signal(SIGINT, &sighandler);

   gsoap.start();

   return EXIT_SUCCESS;
}
person rjoshi    schedule 26.03.2011
comment
Ну, вопрос в том, как изящно завершать потоки gSOAP, а не только в том, как завершать приложение с помощью CTRL-C или чего-то подобного. Я завершаю работу, проверив kbhit сейчас. - person Vladislav Rastrusny; 26.03.2011
comment
Вы можете остановить потоки в этой функции. Я использую ту же функцию для своего многопоточного sip-сервера, где нам нужно изящно останавливать вызовы. - person rjoshi; 26.03.2011
comment
См. правки выше, где используется класс gsoap_test. Объект gsoap_test также может быть передан в качестве аргументов функции sighandler, если вы не хотите делать его глобальным. Другой вариант — использовать функцию boost::signal. - person rjoshi; 26.03.2011
comment
Ну да, но это тот же подход, предложенный @Eddy Pronk, верно? - person Vladislav Rastrusny; 26.03.2011