客户端与服务端WebSocket连接异常问题排查求助
问题分析与修复方案
核心问题
你的后端用Boost.Asio实现的是普通TCP套接字服务,但前端尝试用WebSocket协议连接,两者协议不匹配,导致连接无法建立,因此出现「WebSocket is not open yet. Message not sent」错误。WebSocket是基于HTTP的升级协议,并非原生TCP,直接连接普通TCP端口必然失败。
修复方案
方案一:后端改为WebSocket服务器(推荐)
使用支持WebSocket的库重构后端,你已引入的cpprestsdk(Casablanca)本身支持WebSocket服务,以下是简化实现示例:
#include <cpprest/ws_client.h> #include <cpprest/ws_listener.h> #include <vector> #include <mutex> #include <iostream> #include <cpprest/http_client.h> #include <cpprest/json.h> using namespace web; using namespace web::websockets::server; using namespace web::http; using namespace web::http::client; std::vector<websocket_session> g_clients; std::mutex g_clients_mutex; std::wstring chatWithGPT3(const std::wstring& userMessage) { const utility::string_t apiKey = U("你的API密钥"); web::http::client::http_client client(U("https://api.openai.com/v1/completions")); web::http::http_request request(web::http::methods::POST); request.headers().set_content_type(U("application/json")); request.headers().add(U("Authorization"), U("Bearer ") + apiKey); web::json::value body; body[U("model")] = web::json::value::string(U("davinci-002")); body[U("prompt")] = web::json::value::string(userMessage); body[U("max_tokens")] = web::json::value(50); request.set_body(body); try { web::http::http_response response = client.request(request).get(); if (response.status_code() == web::http::status_codes::OK) { return response.to_string(); } else { std::cerr << "ChatGPT API错误: " << response.status_code() << std::endl; return L"处理请求时出错"; } } catch (const std::exception& e) { std::cerr << "API请求异常: " << e.what() << std::endl; return L"处理请求时出错"; } } void on_message(websocket_session session, websocket_incoming_message msg) { auto user_msg = msg.extract_string().get(); std::wstring gpt_response = chatWithGPT3(utility::conversions::to_wstring_t(user_msg)); std::lock_guard<std::mutex> lock(g_clients_mutex); for (auto& client : g_clients) { if (client != session) { websocket_outgoing_message out_msg; out_msg.set_string(utility::conversions::to_string_t(L"ChatGPT: " + gpt_response)); client.send(out_msg).wait(); } } } void on_open(websocket_session session) { std::lock_guard<std::mutex> lock(g_clients_mutex); g_clients.push_back(session); std::cout << "新客户端连接" << std::endl; } void on_close(websocket_session session) { std::lock_guard<std::mutex> lock(g_clients_mutex); g_clients.erase(std::remove(g_clients.begin(), g_clients.end(), session), g_clients.end()); std::cout << "客户端断开连接" << std::endl; } int main() { try { websocket_listener listener(U("ws://localhost:7000")); listener.set_message_handler(&on_message); listener.set_open_handler(&on_open); listener.set_close_handler(&on_close); listener.open().wait(); std::cout << "WebSocket服务器运行在7000端口..." << std::endl; std::string line; std::getline(std::cin, line); listener.close().wait(); } catch (const std::exception& e) { std::cerr << "服务器启动失败: " << e.what() << std::endl; } return 0; }
方案二:前端改为普通TCP socket(不推荐)
浏览器没有原生普通TCP套接字API(WebRTC DataChannel实现复杂),因此该方案不具备可行性。
前端代码调整
保留原有WebSocket连接逻辑,调整sendMessage触发方式(避免在连接打开时自动发送空消息),添加触发按钮:
<input type="text" id="chat-input" placeholder="输入消息..."> <button onclick="sendMessage()">发送</button> <div id="chat-output"></div>
JavaScript代码无需大改,仅确保sendMessage由用户操作触发即可。
额外检查项
- 先启动后端服务器,再打开前端页面,查看控制台是否打印「WebSocket connection opened」,确认连接建立。
- 用
telnet localhost 7000测试端口连通性,若不通则检查后端是否正确监听7000端口、端口是否被占用。 - ChatGPT API调用的同步等待(
get())会阻塞服务器,高并发场景建议改用异步回调优化。
内容的提问来源于stack exchange,提问作者Shreyash
相关产品推荐
相关产品推荐

