1

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

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

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

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

4

4 回答 4

3

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

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;
}
于 2018-04-20T20:38:42.583 回答
1

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

于 2020-10-03T15:30:56.593 回答
0

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

于 2019-12-27T08:46:01.707 回答
0

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

于 2020-09-20T13:46:19.500 回答