【问题标题】:How to keep server running (cpprestsdk - casablanca)如何保持服务器运行 (cpprestsdk - casablanca)
【发布时间】:2018-04-20 07:22:03
【问题描述】:

我正在使用 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);

保持服务器运行直到我手动停止执行。

不过,我想以更优雅的方式实现此功能。我浏览了在线文档,但未能找到正确的方法。

任何正确方向的提示或指示将不胜感激,因为我以前从未与卡萨布兰卡合作过。感谢您的宝贵时间!

【问题讨论】:

    标签: c++ casablanca cpprest-sdk


    【解决方案1】:

    所以我设法通过使用此处提供的代码来解决这个问题:

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

    【讨论】:

    • 请注意,信号处理程序应具有 C 链接,并且通常仅使用 C 和 C++ 的公共子集的功能。如果具有 C++ 链接的函数可以用作信号处理程序,则由实现定义。
    【解决方案2】:

    std::signal 与接受的anwser 中表示的信号处理程序一起使用并不是真正的选择,因为根据C++ 参考:

    信号处理程序应该有 C 链接,一般来说,只有 使用 C 和 C++ 的公共子集的特性。这是 如果具有 C++ 链接的函数可用作 信号处理程序。

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

    另外,由于 cpprestsdk 依赖于 boost asio,因此可以利用 io_context 进行信号处理。下面的代码 sn-p 演示了这个概念:

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

    【讨论】:

      【解决方案3】:

      我这样做的方法是在 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 请求以终止服务器。

      【讨论】:

        【解决方案4】:

        如果你的 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..";
        }
        
        

        【讨论】:

        • 这是不理想的,因为它不可避免地会使资源泄漏。不是可扩展的解决方案,也不是最佳实践。
        猜你喜欢
        • 1970-01-01
        • 2013-01-26
        • 1970-01-01
        • 2011-07-15
        • 1970-01-01
        • 2012-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多