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

WinHttp WebSocket客户端回调设置求助:C++实现消息监听

WinHttp WebSocket客户端消息接收实现方案

WinHttp没有提供专门的WebSocket消息回调接口,你需要通过线程循环接收或异步IO回调来实现服务器消息监听,以下是具体实现步骤和示例代码:

核心思路

WebSocket协议升级完成后,通过WinHttpWebSocketReceive接口读取服务器消息,结合线程或异步回调实现持续监听。线程循环方式逻辑简单直观,适合快速落地;异步方式则需要配合WinHttpSetStatusCallback处理IO完成事件。

线程循环接收示例代码

假设你已经完成WebSocket协议升级(拿到WINHTTP_WEB_SOCKET_STATUS_CONNECTED状态),以下是独立线程中持续接收消息的实现:

#include <windows.h>
#include <winhttp.h>
#include <iostream>
#include <string>

#pragma comment(lib, "winhttp.lib")

// 已完成协议升级的请求句柄(实际项目建议封装为类成员)
HINTERNET hWebSocketRequest = nullptr;

DWORD WINAPI WebSocketReceiveWorker(LPVOID lpParam) {
    WINHTTP_WEB_SOCKET_BUFFER recvBuffer;
    WINHTTP_WEB_SOCKET_BUFFER_TYPE bufferType;
    DWORD bytesReceived = 0;
    std::string fullMessage;

    const int BUFFER_SIZE = 4096;
    char tempBuffer[BUFFER_SIZE] = {0};

    while (true) {
        // 初始化接收缓冲区
        recvBuffer.Pointer = tempBuffer;
        recvBuffer.Length = BUFFER_SIZE;

        // 阻塞接收WebSocket消息
        DWORD result = WinHttpWebSocketReceive(
            hWebSocketRequest,
            &recvBuffer,
            1,
            &bytesReceived,
            &bufferType
        );

        if (result != ERROR_SUCCESS) {
            std::cerr << "接收失败,错误码: " << result << std::endl;
            break;
        }

        switch (bufferType) {
            case WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE:
                // 拼接UTF-8文本消息
                fullMessage.append(tempBuffer, bytesReceived);
                // 若本次读取未填满缓冲区,说明消息已完整
                if (bytesReceived < BUFFER_SIZE) {
                    std::cout << "收到文本消息: " << fullMessage << std::endl;
                    fullMessage.clear();
                }
                break;

            case WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE:
                // 处理二进制消息
                std::cout << "收到二进制消息,长度: " << bytesReceived << std::endl;
                // 这里可以将二进制数据写入文件或做其他处理
                break;

            case WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE:
                // 收到关闭帧,终止循环
                std::cout << "服务器发起关闭连接" << std::endl;
                goto Cleanup;

            default:
                std::cerr << "未知消息类型" << std::endl;
                break;
        }
    }

Cleanup:
    // 释放请求句柄
    if (hWebSocketRequest) {
        WinHttpCloseHandle(hWebSocketRequest);
        hWebSocketRequest = nullptr;
    }
    return 0;
}

// 启动消息监听
void StartWebSocketListening() {
    if (!hWebSocketRequest) {
        std::cerr << "WebSocket请求句柄无效" << std::endl;
        return;
    }

    HANDLE hThread = CreateThread(
        nullptr,
        0,
        WebSocketReceiveWorker,
        nullptr,
        0,
        nullptr
    );

    if (!hThread) {
        std::cerr << "创建接收线程失败,错误码: " << GetLastError() << std::endl;
        return;
    }

    // 无需等待线程的话可以关闭句柄,线程会后台运行
    CloseHandle(hThread);
}

关键注意事项

  • 分片消息处理:WinHttp会自动处理WebSocket的分片帧,但需要你自行拼接跨多次WinHttpWebSocketReceive调用的消息内容,示例中通过fullMessage字符串拼接实现。
  • 错误处理:如果WinHttpWebSocketReceive返回ERROR_WINHTTP_CONNECTION_ERROR,说明连接已断开,需要终止循环并清理资源。
  • 异步方式可选:若需异步接收,需先通过WinHttpSetOption设置WINHTTP_OPTION_ASYNC,再注册WinHttpSetStatusCallback回调,在WINHTTP_CALLBACK_STATUS_READ_COMPLETE事件触发时调用WinHttpWebSocketReceive读取数据,逻辑相对复杂,适合对主线程无阻塞要求的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:40:52