如何保持服务器 运行 (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);
保持服务器 运行 直到我手动停止执行。
不过,我想以更优雅的方式实现此功能。我浏览了在线文档,但未能找到正确的方法。
任何正确方向的提示或指示将不胜感激,因为我以前从未与卡萨布兰卡合作过。感谢您的宝贵时间!
所以我设法使用此处提供的代码解决了这个问题:
这是我的新 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;
}
我的方法是在 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 会将字符串输入处理为不同的字符,并且循环将执行到字符串的长度,解决方法是忽略其余字符,但我决定做好使用输入(终止服务器的关键字)
其他方法是在 main 中设置一个信号量等待并通过所需的信号释放它,同时以适当的方法 (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..";
}
将 std::signal
与信号处理程序一起使用,如已接受的 anwser 中所述,这里并不是一个真正的选项,因为根据 C++ 参考:
signal handlers are expected to have C linkage and, in general, only
use the features from the common subset of C and C++. It is
implementation-defined if a function with C++ linkage can be used as a
signal handler.
然而,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;
}
我正在使用 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);
保持服务器 运行 直到我手动停止执行。
不过,我想以更优雅的方式实现此功能。我浏览了在线文档,但未能找到正确的方法。
任何正确方向的提示或指示将不胜感激,因为我以前从未与卡萨布兰卡合作过。感谢您的宝贵时间!
所以我设法使用此处提供的代码解决了这个问题:
这是我的新 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;
}
我的方法是在 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 会将字符串输入处理为不同的字符,并且循环将执行到字符串的长度,解决方法是忽略其余字符,但我决定做好使用输入(终止服务器的关键字)
其他方法是在 main 中设置一个信号量等待并通过所需的信号释放它,同时以适当的方法 (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..";
}
将 std::signal
与信号处理程序一起使用,如已接受的 anwser 中所述,这里并不是一个真正的选项,因为根据 C++ 参考:
signal handlers are expected to have C linkage and, in general, only use the features from the common subset of C and C++. It is implementation-defined if a function with C++ linkage can be used as a signal handler.
然而,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;
}