You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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;
}

四、关键说明

  1. 客户端连接修正:移除ws<Client>调用,直接向connect()传递WebSocket行为配置,这是客户端连接的标准方式。
  2. 服务端用户数据修正:改用ws<void>避免创建不必要的Server实例,符合服务端设计逻辑。
  3. 重连逻辑:利用uWebSockets事件循环的setTimeout实现非阻塞式重连,每次断开后延迟2秒尝试重新连接,直到成功建立连接。

内容的提问来源于stack exchange,提问作者Laila

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 23:19:57