Как изящно остановить сервер HTTP2, созданный с помощью nghttp2 asio

Я знаю, как использовать nghttp2 библиотеку asio для создания HTTP2-сервера и клиентских приложений.

В документации говорится, что существуют stop и join API для корректной остановки сервера HTTP2.

Есть ли рабочий пример использования stop и join? В частности, как только вызывается listen_and_serve, поток переходит в цикл занятости. Рекомендуется ли вызывать stop из другого потока? К сожалению, в документации нет подсказки или примера кода.

РЕДАКТИРОВАТЬ:

Вот рабочая программа, в которой я пытаюсь остановить сервер на SIGINT.

#include <iostream>
#include <thread>
#include <nghttp2/asio_http2_server.h>

using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;

nghttp2::asio_http2::server::http2 myserver;
void signalHandler( int signum ) {
  std::cout << "Interrupt signal (" << signum << ") received." << std::endl;
  myserver.stop();
  myserver.join();
  exit(0);
}

int main(int argc, char *argv[]) {
  signal(SIGINT, signalHandler);
  std::thread::id this_id = std::this_thread::get_id();
  std::cout << "Main thread running at " << this_id << std::endl;
  boost::system::error_code ec;

  myserver.handle("/api/ping", [](const request &req, const response &res) {
    std::thread::id this_id = std::this_thread::get_id();
    std::cout << "Ping Request received at " << this_id << std::endl;
    req.on_data([](const uint8_t *data, std::size_t len){
      std::cerr.write(reinterpret_cast<const char *>(data), len);
      std::cerr << std::endl;
    });
    res.write_head(200);
    res.end("hello, ping\n");
  });

  if (myserver.listen_and_serve(ec, "0.0.0.0", "8080")) {
    std::cerr << "error: " << ec.message() << std::endl;
  }
}

Выполнение зависает на myserver.stop() после нажатия Control+C. Я пытался использовать только myserver.stop() или myserver.join(), но без каких-либо улучшений. Если я напрямую вызову exit(0), как показано ниже, сервер остановится с ошибкой сегментации.

void signalHandler( int signum ) {
  std::cout << "Interrupt signal (" << signum << ") received." << std::endl;
  myserver.stop();
  myserver.join();
  exit(0);
}

Любая помощь приветствуется.


person Soumya Kanti    schedule 01.11.2018    source источник


Ответы (1)


Параметр asynchronous в listen_and_serve должен быть установлен на true, по умолчанию asynchronous = false.

Обратите внимание, что сервер не выйдет и не будет ждать myserver.join(), пока не будет закрыто последнее клиентское соединение. При вызове myserver.close() сервер перестает принимать новые подключения.

Рабочее решение ниже:

#include <iostream>
#include <thread>
#include <nghttp2/asio_http2_server.h>

using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;

nghttp2::asio_http2::server::http2 myserver;
void signalHandler( int signum ) {
  std::cout << "Interrupt signal (" << signum << ") received." << std::endl;
  myserver.stop();
}

int main(int argc, char *argv[]) {
  signal(SIGINT, signalHandler);
  std::thread::id this_id = std::this_thread::get_id();
  boost::system::error_code ec;

  myserver.handle("/api/ping", [](const request &req, const response &res) {
    std::thread::id this_id = std::this_thread::get_id();
    std::cout << "Ping Request received at " << this_id << std::endl;
    req.on_data([](const uint8_t *data, std::size_t len){
      std::cerr.write(reinterpret_cast<const char *>(data), len);
      std::cerr << std::endl;
    });
    res.write_head(200);
    res.end("hello, ping\n");
  });

  if (myserver.listen_and_serve(ec, "0.0.0.0", "8080", true)) {
    std::cerr << "error: " << ec.message() << std::endl;
  }
  myserver.join();
}
person Soumya Kanti    schedule 09.11.2018