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
相关产品推荐
相关产品推荐

