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

如何用WinHTTP检测WebSocket连接断开?C++客户端适配CC:Tweaked

C++ WebSocket客户端连接断开检测问题

重要背景

  • 开发C++客户端,用于连接WebSocket服务器(对接Minecraft的CC:Tweaked模组计算机,必须使用WebSocket),服务器由第三方搭建无法控制。
  • 曾因连接问题采用他人提供的方案(结合WinHTTP自行修改)实现客户端,初步排查代码无明显缺陷,但无法完全确认。

当前问题

服务器完全终止后,客户端无法感知连接断开,仍会尝试发送数据;调用发送函数时程序会冻结,等待永远不会到来的响应,直到强制关闭。需要实现连接断开检测,提示用户并禁用发送功能,直到重新连接。

相关代码

客户端类基于WinHTTP实现WebSocket通信,包含实现文件(WebSocketClient.cpp)和头文件(WebSocketClient.h)。

调用示例

在wxWidgets程序中调用客户端发送数据的代码:

json Client::Chat(std::string guid, std::string label, std::string data) {
    json message = {
        {"id", guid},
        {"label", label},
        {"data", data}
    };

    if (client.Send(message)) {
        std::string response = client.Receive();

        try {
            json responseJson = json::parse(response);
            return responseJson;
        }
        catch (json::parse_error& e) {
            return nullptr;
        }
    }
    return nullptr;
}

核心痛点

上述Chat函数无法感知连接状态,服务器关闭后调用会导致程序无响应,需避免冻结并及时检测连接中断。

疑问

了解到TCP keepalive机制,但不确定是否适用;需求是连接断开时立即终止当前连接,直到重新手动建立,而非保持连接,怀疑自己对网络机制的认知有偏差。


解决方案

1. WinHTTP错误码捕获与状态标记

WinHTTP的发送/接收操作失败时,可通过GetLastError()获取明确的连接错误信号:

  • 捕获ERROR_CONNECTION_ABORTED(连接被中止)、ERROR_CONNECTION_RESET(连接被重置)等错误码,在Send和Receive方法中设置bool m_isConnected状态标志,后续发送前先检查该标志。

2. 给WinHTTP操作设置超时

当前Receive为阻塞式无超时逻辑,导致程序冻结。通过WinHttpSetOption设置超时参数:

// 设置发送和接收超时为5秒
DWORD timeout = 5000;
WinHttpSetOption(hRequest, WINHTTP_OPTION_SEND_TIMEOUT, &timeout, sizeof(timeout));
WinHttpSetOption(hRequest, WINHTTP_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(timeout));

超时触发后,操作会返回失败,借此标记连接为断开状态。

3. 启用TCP Keepalive机制

TCP keepalive完全适配你的场景,它会定期发送探测包检测对方在线状态,连续探测无响应时系统会标记连接断开。通过WinHTTP启用:

WINHTTP_KEEPALIVE_INFO keepAliveInfo = {
    TRUE,  // 启用keepalive
    5000,  // 5秒发送一次探测包
    1000   // 重试间隔1秒
};
WinHttpSetOption(hRequest, WINHTTP_OPTION_KEEPALIVE, &keepAliveInfo, sizeof(keepAliveInfo));

启用后,服务器关闭时WinHTTP操作会返回错误,可及时更新连接状态。

4. 异步化通信避免UI冻结

在wxWidgets程序中,同步阻塞的Receive会导致UI无响应,需将WebSocket通信放到单独线程:

  • 创建工作线程处理发送/接收,检测到连接断开时,通过wxPostEvent向UI线程发送事件,更新UI状态(禁用发送按钮、提示用户)。

5. 利用WebSocket Ping/Pong机制主动验证

WebSocket协议内置Ping/Pong帧机制,可在客户端主动发送Ping帧:

  • 发送Ping帧后等待Pong响应,超时未收到则判定连接断开,标记状态并提示用户。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:13:15