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

uWebSockets C++发送报错:cork buffer未检查cancork致崩溃

嵌入式WebSocket服务器崩溃问题排查

问题背景

我正在为嵌入式系统开发WebSocket服务器,核心需求是向WebApp订阅的信号ID列表推送更新。原本运行正常,但近期频繁出现崩溃,怀疑和corking机制有关,且在多种场景下都能复现。我自行实现了发布/订阅机制,通过独立线程以每秒10次的频率异步向客户端发送包含多信号更新的批量消息。崩溃似乎发生在发送操作与message回调冲突的场景下。

应用配置代码

auto app
    = uWS::App()
          .ws<ClientData>(
              "/*", { /* Settings */
                      .compression      = uWS::CompressOptions(uWS::DEDICATED_COMPRESSOR_4KB | uWS::DEDICATED_DECOMPRESSOR),
                      .maxPayloadLength = 100 * 1024 * 1024,
                      .idleTimeout      = 16,
                      .maxBackpressure  = 100 * 1024 * 1024,
                      .closeOnBackpressureLimit = false,
                      .resetIdleTimeoutOnSend   = false,
                      .sendPingsAutomatically   = true,
                      /* Handlers */
                      // handshaking callback
                      .upgrade =
                          [this](auto *res, auto *req, auto *context)
                      {
                          auto subprotocols = String(req->getHeader("sec-websocket-protocol"));
                          auto jwt          = this->GetJwtFromSubprotocols(subprotocols);

                          if(!this->ValidateJwt(jwt))
                          {
                              res->writeStatus("401");
                              res->end("Invalid jwt");
                              return;
                          }

                          if(this->IsMaximumCapacityReached())
                          {
                              res->writeStatus("503");
                              res->end("Maximum number of clients reached");
                              return;
                          }

                          res->upgrade(ClientData{}, req->getHeader("sec-websocket-key"),
                                       req->getHeader("sec-websocket-protocol"), req->getHeader("sec-websocket-extensions"),
                                       context);
                      },
                      .open    = [this](auto *ws) { this->OnOpen(ws); },
                      .message = [this](auto *ws, std::string_view message, uWS::OpCode) { this->OnMessage(ws, message); },
                      .dropped =
                          [](auto * /*ws*/, std::string_view /*message*/, uWS::OpCode /*opCode*/)
                      {
                          /* A message was dropped due to set maxBackpressure and closeOnBackpressureLimit limit */
                      },
                      .drain =
                          [](auto * /*ws*/)
                      {
                          /* Check ws->getBufferedAmount() here */
                      },
                      .ping =
                          [](auto * /*ws*/, std::string_view)
                      {
                          /* Not implemented yet */
                      },
                      .pong =
                          [](auto * /*ws*/, std::string_view)
                      {
                          /* Not implemented yet */
                      },
                      .close = [this](auto *ws, int /*code*/, std::string_view /*message*/) { this->OnClose(ws); } })
          .listen("127.0.0.1", 50000,
                  [](auto *listen_socket)
                  {
                      if(listen_socket)
                      {
                          LogDebug("Ready on port 50000");
                      }
                  });

发送线程逻辑

发送线程通过互斥锁保护,循环执行以下代码:

Sync lock(*_clientsMutex);
for(auto client : *_clients)
{
    SendRealtimeUpdate(client);
}

其中SendRealtimeUpdate方法处理后生成std::string类型的消息,通过client->send(msg, uWS::OpCode::TEXT);发送。

已尝试方案与疑问

试过uWebSockets内置的发布/订阅机制(以信号ID为主题),该机制运行稳定,但只能单信号发送,效率太低,不符合批量推送的需求。我猜测问题根源是message回调和线程发送操作之间缺少同步机制。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:14:56