如何使用Boost正确重连TCP socket并保持服务持续监听运行
解决方案
崩溃根因
- Boost.Beast的WebSocket操作在连接断开、读写异常时会抛出
boost::wrapexcept<boost::system::system_error>类型异常,未捕获的异常会直接触发程序终止。 - 你当前贴出的代码仅实现了TCP端口监听逻辑,实际触发报错的是你完整代码中未贴出的WebSocket握手、数据收发逻辑。
改造实现
你需要为每个客户端连接单独分配线程处理,同时为所有WebSocket操作加异常捕获,避免单个客户端异常导致整个服务崩溃,改造后的参考代码如下:
#include <boost/beast/core.hpp> #include <boost/beast/websocket.hpp> #include <iostream> #include <string> #include <thread> using tcp = boost::asio::ip::tcp; namespace websocket = boost::beast::websocket; // 单个客户端连接的业务处理逻辑 void handle_client(tcp::socket socket) { try { // 初始化WebSocket流 websocket::stream<tcp::socket> ws(std::move(socket)); // 接受WebSocket握手 ws.set_option(websocket::stream_base::timeout::suggested(boost::beast::role_type::server)); ws.accept(); std::cout << "客户端WebSocket连接建立成功" << std::endl; // 循环读写数据 boost::beast::flat_buffer buffer; while (true) { // 读取客户端数据 ws.read(buffer); // 原样回写数据(可替换为你的业务逻辑) ws.write(buffer.data()); buffer.consume(buffer.size()); } } catch (const boost::system::system_error& e) { // 捕获连接断开异常,仅打印日志不终止程序 if (e.code() == websocket::error::closed) { std::cout << "客户端已正常断开连接" << std::endl; } else { std::cout << "连接异常:" << e.what() << std::endl; } } catch (const std::exception& e) { std::cout << "业务处理异常:" << e.what() << std::endl; } // 线程执行结束自动释放连接资源 } int main() { try { auto const address = boost::asio::ip::make_address("127.0.0.1"); auto const port = static_cast<unsigned short>(std::atoi("8080")); boost::asio::io_context ioc{1}; tcp::acceptor acceptor{ioc, {address, port}}; std::cout << "服务端启动成功,监听端口:" << port << std::endl; while (true) { tcp::socket socket{ioc}; // 阻塞等待新客户端连接 acceptor.accept(socket); std::cout << "新TCP连接接入" << std::endl; // 启动独立线程处理该客户端逻辑,不阻塞主线程监听 std::thread(handle_client, std::move(socket)).detach(); } } catch (const std::exception& e) { std::cout << "服务端核心异常:" << e.what() << std::endl; return 1; } }
可选:固定IP客户端自动重连逻辑
如果你需要的是作为客户端主动连接指定服务端,断开后自动重连,只需要在客户端逻辑外层加循环即可:
void client_reconnect_logic() { auto const address = boost::asio::ip::make_address("127.0.0.1"); auto const port = static_cast<unsigned short>(std::atoi("8080")); while (true) { try { boost::asio::io_context ioc; tcp::socket socket(ioc); tcp::resolver resolver(ioc); boost::asio::connect(socket, resolver.resolve(address, std::to_string(port))); websocket::stream<tcp::socket> ws(std::move(socket)); ws.handshake("127.0.0.1", "/"); // 后续业务逻辑... } catch (const std::exception& e) { std::cout << "连接断开,3秒后尝试重连:" << e.what() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(3)); } } }
内容的提问来源于stack exchange,提问作者Alvydas Juodikis
相关产品推荐
相关产品推荐

