前端连接C++ WebSocket服务器时出现SSL错误求助
WebSocket服务器SSL连接错误修复方案
错误原因解析
00B6571701000000:error:0A00009C:SSL routines:ssl3_get_record:http request 这个错误表示SSL层接收到了纯HTTP请求,而非TLS握手数据包。核心问题集中在三点:
- 前端连接协议与服务器加密配置不匹配
- 数据收发绕过了SSL加密层
- 未实现WebSocket必须的HTTP升级握手流程
分步修复方案
1. 修正前端连接地址
服务器配置了TLS加密,前端必须使用wss://协议连接,而非ws://。示例:
const ws = new WebSocket('wss://localhost:你的端口号');
2. 替换为SSL专用收发函数
当前代码直接调用::send和recv操作原始socket,完全绕过了SSL加密层,必须替换为OpenSSL提供的SSL_write和SSL_read:
void WebSocketTCPServer::send(Connection *connection, const std::string& message) { SSL_write(connection->ssl, message.c_str(), message.length()); } std::string WebSocketTCPServer::receive(Connection *connection) { char buffer[1024] = {0}; int valread = SSL_read(connection->ssl, buffer, 1024); return {buffer, static_cast<size_t>(valread)}; }
3. 实现WebSocket HTTP升级握手
WebSocket连接建立前必须完成HTTP Upgrade握手,处理步骤如下:
#include <openssl/sha.h> // 需自行实现Base64编码,可借助OpenSSL的EVP_EncodeBlock函数 std::string base64_encode(const unsigned char* data, size_t len) { BIO *bio, *b64; BUF_MEM *bufferPtr; b64 = BIO_new(BIO_f_base64()); bio = BIO_new(BIO_s_mem()); bio = BIO_push(b64, bio); BIO_write(bio, data, len); BIO_flush(bio); BIO_get_mem_ptr(bio, &bufferPtr); BIO_set_close(bio, BIO_NOCLOSE); std::string result(bufferPtr->data, bufferPtr->length - 1); // 去掉末尾换行 BIO_free_all(bio); return result; } void WebSocketTCPServer::handleConnection(Connection *connection) { // 读取客户端HTTP升级请求 std::string req = receive(connection); // 提取Sec-WebSocket-Key(简化实现,实际需完整解析HTTP头) size_t keyPos = req.find("Sec-WebSocket-Key: "); if (keyPos == std::string::npos) { closeConnection(connection); return; } std::string key = req.substr(keyPos + 19, 24); // 计算响应密钥(结合WebSocket标准magic字符串) std::string magic = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; unsigned char sha1Result[20]; SHA1(reinterpret_cast<const unsigned char*>(magic.c_str()), magic.length(), sha1Result); std::string acceptKey = base64_encode(sha1Result, 20); // 返回升级响应 std::string resp = "HTTP/1.1 101 Switching Protocols\r\n"; resp += "Upgrade: websocket\r\n"; resp += "Connection: Upgrade\r\n"; resp += "Sec-WebSocket-Accept: " + acceptKey + "\r\n\r\n"; send(connection, resp); // 握手完成后,才能处理WebSocket帧数据 std::string msg = receive(connection); printf("%s", msg.c_str()); }
4. 适配OpenSSL 3.x初始化API
你当前使用的SSL_library_init()等是旧版API,OpenSSL 3.x推荐使用新初始化方式:
void WebSocketTCPServer::startServer(int port) { // 替换旧初始化代码 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); const SSL_METHOD* method = TLS_server_method(); // 自动适配最新TLS版本 // 后续证书加载、socket创建逻辑保持不变... }
额外注意事项
- 确保
cert.pem和key.pem文件路径正确,且进程有读取权限 - 测试时需处理浏览器对自签名证书的安全提示(或手动添加信任)
- 多线程场景下需初始化OpenSSL线程锁,避免并发问题
内容的提问来源于stack exchange,提问作者Pixel Coin
相关产品推荐
相关产品推荐

