簡體   English   中英

如何保持服務器運行 (cpprestsdk - casablanca)

[英]How to keep server running (cpprestsdk - casablanca)

我正在使用 Microsoft 的 cpprestsdk(又名 casablanca)開發 REST api,並且在執行我的代碼時無法保持服務器運行。

在此處查看我的 main.cpp:

int main() {
    cout << "Starting Server" << endl;

    TransactionController server;
    server.setEndpoint("http://0.0.0.0:4200/api");
    server.initHandlers();

    try {
        server.openServer();
        cout << "Server listening at: " << server.getEndpoint() << endl;

        // figure out how to keep server running without this?
        while (true);
    }
    catch(exception &e) {
        cout << "--- ERROR DETECTED ---" << endl;
        cout << e.what() << endl;
    }


    // this doesn't get reached bc of the while(true)
    server.closeServer();

    return 0;
}

此外,作為參考,這是我在 main.cpp 中的實現或功能:

pplx::task<void> TransactionController::openServer() {
    return listener.open();
}

pplx::task<void> TransactionController::closeServer() {
    return listener.close();
}

std::string TransactionController::getEndpoint() const{
    return listener.uri().to_string();
}


void TransactionController::initHandlers() {
    listener.support(methods::GET, bind(&TransactionController::handleGet, this, std::placeholders::_1));
    listener.support(methods::POST, bind(&TransactionController::handlePost, this, placeholders::_1));
}

void TransactionController::setEndpoint(const string& value) {
    listener = http_listener(value);
}

我發現添加一個不理想的解決方法

while(true);

保持服務器運行,直到我手動停止執行。

但是,我想以更優雅的方式實現此功能。 我已經在線瀏覽了文檔,但無法找到正確的方法。

任何正確方向的提示或指示將不勝感激,因為我以前從未與卡薩布蘭卡合作過。 謝謝你的時間!

所以我設法通過使用這里提供的代碼來弄清楚:

https://github.com/ivanmejiarocha/micro-service/blob/master/source/foundation/include/usr_interrupt_handler.hpp

現在是我的新 main.cpp:

int main() {
    cout << "Starting Server" << endl;

    InterruptHandler::hookSIGINT();

    TransactionController server;
    server.setEndpoint("http://0.0.0.0:4200/api");
    server.initHandlers();

    try {
        server.openServer().wait();
        cout << "Server listening at: " << server.getEndpoint() << endl;

        InterruptHandler::waitForUserInterrupt();

        server.closeServer().wait();
        cout << "Shutting Down Server" << endl;
    }
    catch(exception &e) {
        cout << "--- ERROR DETECTED ---" << endl;
        cout << e.what() << endl;
    }    

    return 0;
}

std::signal與接受的 anwser 中表示的信號處理程序一起使用並不是真正的選項,因為根據 C++ 參考:

信號處理程序應具有 C 鏈接,並且通常僅使用來自 C 和 C++ 公共子集的功能。 如果具有 C++ 鏈接的函數可以用作信號處理程序,則它是實現定義的。

然而, notify_{one,all}不是信號安全的,因此不能在信號處理程序中使用。

或者,由於 cpprestsdk 依賴於 boost asio,因此可以利用 io_context 進行信號處理。 下面的代碼片段演示了這個概念:

void handle_get(web::http::http_request request) {
  //...
}

void interrupt_handler( const boost::system::error_code& error , int signal_number ) {
  //...
}

int main() {

  using web::http::experimental::listener::http_listener;
  auto url = web::http::uri("http://127.0.0.1:8051");

  http_listener listener(url);
  listener.support(web::http::methods::GET, handle_get);
  listener.open().then([]() { std::cout << "listening ..." << std::endl; }).wait();

  boost::asio::io_context handler_context;
  boost::asio::signal_set signals(handler_context, SIGINT );

  signals.async_wait( interrupt_handler );
  handler_context.run();

  return 0;
}

一種方法是將start調用委托給線程,並為while循環添加一個標志(例如isClosed )以關閉信號(為此檢查std::atomic )。 並且,您的close調用會將isClosed設置為true ,線程將正常退出。 不要忘記調用線程的join在你的類的析構函數。

這是服務器線程回調的示例:

void YourClass::startThreadCallback()
{
    // Start listener here...

    while ( !isClosed )
    {
        std::this_thread::sleep_for( 1ms );
    }
}

我這樣做的方法是在 do-while 循環中使用 std::getline ,它只能通過正確的命令終止服務器。 我發現這是一個快速解決方案,資源匱乏。

    http_listener listener(L"http://localhost:80");

    try {
        listener
            .open()
            .then([&listener]() {std::wcout << L"\nstarting to listen\n"; })
            .wait();
    } catch(exception const& e){
        std::wcout << e.what() << std::endl;
    }

    std::string choice= "";
    do {
        std::getline(cin, choice);
    } while (!(choice == "N" || choice == "n"));
    return 0;

注意:普通的 std::cin 會將字符串輸入處理為不同的字符,並且循環將被執行直到字符串的長度,解決方法是忽略其余的字符,但我決定充分利用輸入(關鍵字終止服務器)

其他方法是在主程序中設置信號量等待並通過所需的信號釋放它,同時以適當的方法(GET/PUT/POST/DELETE)處理服務器終止的 HTTP 請求。

如果您的 http_listener 是指針,則可以避免無限循環。 創建一個 http_listener 對象並等待,您應該能夠消除無限循環並繼續程序。

以下代碼有效,

void initialize() {
    http_listener *listener;
    listener = new http_listener(L"http://127.0.0.1:1444/vessel");
    listener->support(methods::GET, get_vessel_visitpositions);

    try
    {
        listener->
            open()
            .then([&listener](){})
            .wait();

        //while (true);
    }
    catch (exception const & e)
    {
        wcout << e.what() << endl;
        return;
    }

    cout<<"Listening started..";
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM