如何用uWebSockets库创建WebSocket服务端/客户端及解决连接与重连问题
问题解决与重连实现方案
一、客户端无法连接的问题修复
你的代码存在两个关键问题导致客户端连接失败:
1. 客户端错误使用ws()方法
uWS::App::ws()是服务端用于注册WebSocket路由的API,客户端连接时完全不需要调用该方法。正确做法是直接将WebSocketBehavior配置传递给connect()方法。
2. 服务端用户数据类型错误
服务端使用ws<Server>("/*", ...)会为每个WebSocket连接创建一个新的Server实例,这违背了Server类作为服务端管理器的设计意图。应使用ws<void>表示不需要单连接专属用户数据。
二、客户端重连实现
当服务端重启或连接断开时,客户端需要通过事件循环定时器调度重连尝试,避免阻塞事件循环。核心实现步骤:
- 将连接逻辑封装为独立方法,方便重复调用
- 在
close回调中使用setTimeout延迟触发重连 - 设置合理的重连间隔(示例中为2秒)
三、完整修正代码
#include <uwebsockets/App.h> #include <thread> #include <iostream> #include <chrono> class Server { public: bool connected = false; void runServer() { // 使用ws<void>,不需要单连接用户数据 uWS::App().ws<void>("/*", { .open = [](auto* ws) { ws->subscribe("broadcast"); std::cout << "Server: Client connected" << std::endl; }, .message = [](auto* ws, std::string_view message, uWS::OpCode opCode) { ws->publish("broadcast", message, opCode); std::cout << "Server: Received and broadcast message: " << message << std::endl; }, .close = [](auto* ws, int code, std::string_view message) { std::cout << "Server: Client disconnected" << std::endl; } }).listen(9001, [this](auto* listen_socket) { if (listen_socket) { std::cout << "Server listening on port 9001" << std::endl; connected = true; } }).run(); } }; class Client { private: uWS::App app; const std::chrono::seconds reconnectDelay = std::chrono::seconds(2); // 封装连接逻辑,方便重连调用 void connectToServer() { app.connect("ws://localhost:9001", nullptr, uWS::App::WebSocketBehavior<void> { .open = [](auto* ws) { std::cout << "Client: Connected to server" << std::endl; ws->send("Hello from client!", uWS::OpCode::TEXT); }, .message = [](auto* ws, std::string_view message, uWS::OpCode opCode) { std::cout << "Client: Received message: " << message << std::endl; }, .close = [this](auto* ws, int code, std::string_view message) { std::cout << "Client: Disconnected from server, will reconnect in " << reconnectDelay.count() << " seconds" << std::endl; // 使用事件循环定时器调度重连,避免阻塞 app.getLoop()->setTimeout([this](auto*) { connectToServer(); }, reconnectDelay.count() * 1000); // 转换为毫秒 } }); } public: void runClient() { connectToServer(); app.run(); } }; int main() { Server server; std::thread server_thread([&server]() { server.runServer(); }); while (!server.connected) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } Client client; client.runClient(); server_thread.join(); return 0; }
四、关键说明
- 客户端连接修正:移除
ws<Client>调用,直接向connect()传递WebSocket行为配置,这是客户端连接的标准方式。 - 服务端用户数据修正:改用
ws<void>避免创建不必要的Server实例,符合服务端设计逻辑。 - 重连逻辑:利用uWebSockets事件循环的
setTimeout实现非阻塞式重连,每次断开后延迟2秒尝试重新连接,直到成功建立连接。
内容的提问来源于stack exchange,提问作者Laila
相关产品推荐
相关产品推荐

