修改已知bug

This commit is contained in:
cxh 2026-01-22 09:37:29 +08:00
parent 209258589e
commit 222e816d5e

View File

@ -45,21 +45,24 @@ void TunnelClient::start()
void TunnelClient::stop() void TunnelClient::stop()
{ {
running_.store(false); running_.store(false);
if (client_)
ws_client* cli = client_; // 拷贝一份,避免 race
if (cli)
{ {
client_->get_io_service().post( cli->get_io_service().post(
[this]() [this, cli]()
{ {
try try
{ {
websocketpp::lib::error_code ec; websocketpp::lib::error_code ec;
client_->close(hdl_, websocketpp::close::status::going_away, "stop", ec); cli->close(hdl_, websocketpp::close::status::going_away, "stop", ec);
} }
catch (...) catch (...)
{ {
} }
}); });
} }
if (th_.joinable()) th_.join(); if (th_.joinable()) th_.join();
} }
@ -204,11 +207,23 @@ void TunnelClient::handle_request_and_reply(const json& req)
void TunnelClient::run_loop() void TunnelClient::run_loop()
{ {
while (running_.load())
{
// 每次循环都创建一个新的 client避免 websocketpp 状态复用崩溃
ws_client c; ws_client c;
c.clear_access_channels(websocketpp::log::alevel::all); c.clear_access_channels(websocketpp::log::alevel::all);
c.clear_error_channels(websocketpp::log::elevel::all);
c.init_asio(); c.init_asio();
// (可选但推荐)让 run() 不会因为没有 work 而提前退出
c.start_perpetual();
// 让 stop() 能安全拿到当前 client
{
// 如果你不想引入 mutex这段也可以不加但建议加
client_ = &c; client_ = &c;
}
c.set_open_handler( c.set_open_handler(
[this](websocketpp::connection_hdl h) [this](websocketpp::connection_hdl h)
@ -217,9 +232,23 @@ void TunnelClient::run_loop()
std::printf("[Tunnel] Connected to server\n"); std::printf("[Tunnel] Connected to server\n");
}); });
c.set_close_handler([this](websocketpp::connection_hdl) { std::printf("[Tunnel] Disconnected from server\n"); }); c.set_close_handler(
[this, &c](websocketpp::connection_hdl)
{
std::printf("[Tunnel] Disconnected from server\n");
// 让 run() 退出,进入下一轮重连
c.stop_perpetual();
c.stop();
});
c.set_fail_handler([this](websocketpp::connection_hdl) { std::printf("[Tunnel] Connect failed\n"); }); c.set_fail_handler(
[this, &c](websocketpp::connection_hdl)
{
std::printf("[Tunnel] Connect failed\n");
// 让 run() 退出,进入下一轮重连
c.stop_perpetual();
c.stop();
});
c.set_message_handler( c.set_message_handler(
[this](websocketpp::connection_hdl, ws_client::message_ptr msg) [this](websocketpp::connection_hdl, ws_client::message_ptr msg)
@ -231,10 +260,9 @@ void TunnelClient::run_loop()
std::printf("[Tunnel] ignore non-text msg from server\n"); std::printf("[Tunnel] ignore non-text msg from server\n");
return; return;
} }
auto payload = msg->get_payload(); json req = json::parse(msg->get_payload());
json req = json::parse(payload);
// 同步处理会阻塞 websocket 线程:这里开线程处理,避免卡住心跳/读写 // 你原来的做法:起线程处理本地 HTTPOK
std::thread( std::thread(
[this, req]() [this, req]()
{ {
@ -269,18 +297,16 @@ void TunnelClient::run_loop()
{ {
std::printf("[Tunnel] Connection init failed: %s\n", ec.message().c_str()); std::printf("[Tunnel] Connection init failed: %s\n", ec.message().c_str());
client_ = nullptr; client_ = nullptr;
return; // 这里别直接 return继续重试
goto retry_sleep;
} }
c.connect(conn); c.connect(conn);
// 用 run():稳定事件循环
while (running_.load())
{
try try
{ {
// 阻塞运行,直到 fail/close 里 stop(),或 stop() 主动 close
c.run(); c.run();
// run() 返回说明 stopped 了,稍等再重连
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -291,25 +317,15 @@ void TunnelClient::run_loop()
std::printf("[Tunnel] run unknown exception\n"); std::printf("[Tunnel] run unknown exception\n");
} }
client_ = nullptr;
if (!running_.load()) break; if (!running_.load()) break;
retry_sleep:
std::printf("[Tunnel] reconnecting in 2s...\n"); std::printf("[Tunnel] reconnecting in 2s...\n");
std::this_thread::sleep_for(std::chrono::seconds(2)); std::this_thread::sleep_for(std::chrono::seconds(2));
// 重建连接
c.reset();
c.init_asio();
websocketpp::lib::error_code ec2;
auto conn2 = c.get_connection(ws_url_, ec2);
if (ec2)
{
std::printf("[Tunnel] reconnect init failed: %s\n", ec2.message().c_str());
continue;
}
c.connect(conn2);
} }
std::printf("[Tunnel] Loop exit\n");
client_ = nullptr; client_ = nullptr;
std::printf("[Tunnel] Loop exit\n");
} }