我正在尝试使用 REST 服务器发送 boost/asio IP 命令,但看起来好像什么也没发生。为了获得更好的上下文,我有一种方法可以在看门狗定时器超时时发送 IP 命令;如果我在 REST 监听方法之前调用该函数,命令将被发送并且一切正常,但是一旦 REST 服务器启动,我就无法再使用 boost/asio。我对 boost/asio 不是很有经验,所以我很困惑。
这是我的代码基本结构的示例:
#include <iostream>
#include <boost/asio.hpp>
#include "../include/httplib.h"
#include "../include/json.hpp"
using boost::asio::ip::tcp;
static boost::asio::io_context io_context;
static tcp::socket testSocket(io_context);
boost::system::error_code boost_error;
std::string testIP = "192.168.9.114";
std::string testPort = "20000";
int serverPort__ = 8077;
static httplib::Server server_;
namespace RestServer {
std::string what(const std::exception_ptr &eptr = std::current_exception()) {
if (!eptr) { throw std::bad_exception(); }
try { std::rethrow_exception(eptr); }
catch (const std::exception &e) { return e.what() ; }
catch (const std::string &e) { return e ; }
catch (const char *e) { return e ; }
catch (...) { return "who knows"; }
}
int main() {
std::cout << "Starting REST server at port " << serverPort__ << std::endl;
if (!server_.is_valid()) {
std::cout << "Rest server has an error..." << std::endl;
return -1;
}
server_.Get("/stop", [&](const httplib::Request &req, httplib::Response &res) {
std::cout << "Rest server is stopping..." << std::endl;
(void)req;
(void)res;
server_.stop();
});
server_.set_error_handler([](const httplib::Request &req, httplib::Response &res) {
const char *fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
char buf[BUFSIZ];
if (res.body.length() > 4) {
snprintf(buf, sizeof(buf), "<p>Error Status: <span style='color:red;'>%d</span></p><p>Message: %s</p>", res.status, res.body.c_str());
}
else {
snprintf(buf, sizeof(buf), fmt, res.status);
}
res.set_content(buf, "text/html");
});
server_.set_exception_handler([](const httplib::Request &req, httplib::Response &res, std::exception_ptr ep) {
std::cout << "REST Exception! " << what(ep) << std::endl;
});
server_.Get("/TEST", [](const httplib::Request &req, httplib::Response &res) {
nlohmann::json jsonRes;
std::string cmdStr = req.get_param_value("cmd");
std::string opStr = req.get_param_value("op");
uint8_t operation = 0;
uint8_t command = 0;
try {
operation = std::stoi(opStr);
command = std::stoi(cmdStr);
}
catch (std::exception &_) {
res.body = "Bad operation/command/addr/numBytes";
res.status = 400;
return;
}
switch (operation) {
case 0: {
switch (command) {
case 1: {
// example of boost/asio method done via rest
sendTestIPCommand(0x02, 0x01);
}
}
}
case 1: {
switch (command) {
case 1: {
// other read commands
}
}
}
}
res.set_content(jsonRes.dump(), "application/json");
});
server_.listen("0.0.0.0", serverPort__);
std::cout << "Quitting REST server at port" << serverPort__ << std::endl;
return 0;
}
}
void startTestSocket() {
try {
testSocket = tcp::socket(io_context);
tcp::resolver signalLightResolver(io_context);
tcp::resolver::results_type signalLightEndpoints = signalLightResolver.resolve(tcp::resolver::query(tcp::v4(), testIP, testPort));
boost::asio::connect(testSocket, signalLightEndpoints);
}
catch (std::exception &e) {
std::cerr << "Socket Exception: " << e.what() << std::endl;
}
}
void sendTestIPCommand(uint8_t color, uint8_t mode) {
unsigned char c_pIdataW[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
c_pIdataW[0] = 'W';
c_pIdataW[color] = mode;
auto start_time = std::chrono::steady_clock::now();
try {
while (true) {
boost::asio::write(testSocket, boost::asio::buffer(c_pIdataW), boost_error);
auto now = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::seconds>(now - start_time).count() > 3) {
std::cout << "socket start break" << std::endl;
break;
}
}
}
catch (std::exception &e) {
std::cerr << "Socket Exception: " << e.what() << std::endl;
}
if (!boost_error) {
std::cout << "starting signal light.." << std::endl;
}
else {
std::cerr << "a socket error has occurred" << std::endl;
}
}
int main() {
startTestSocket();
return RestServer::main();
}
如果您有任何关于原因或可能的解决方案的外部信息,我们将不胜感激!
我尝试过多线程:为其余服务器创建了一个唯一的线程,希望允许 REST 对 boost/asio 函数是非阻塞的。为 io_context 创建了一个独特的线程,希望允许 boost/asio 函数非阻塞地休息。我在这两种情况下都尝试过互斥。我已经尝试过 boost/asio 的异步写入方法,但不太确定我对此的期望,因为这是 GPT-4o 推荐的最后努力。