Electron React请求本地C++ HTTP服务器遇net::ERR_CONNECTION_RESET问题
问题
本地运行C++编写的HTTP服务器,通过动态端口向Electron React前端传输数据。服务器已确认正常:curl可获取响应,Firefox能打开生成的JSON数据,但Chrome/Electron无法访问——请求已启用的8080端口时返回:
Trying to fetch data from http://localhost:8080/simdata
GET http://localhost:8080/simdata net::ERR_CONNECTION_RESET
请求未使用的端口(如8083)则返回:
GET http://localhost:8083/simdata net::ERR_CONNECTION_REFUSED
已尝试改用127.0.0.1替代localhost、配置allowInsecureContent、调整CORS设置、禁用缓存等方案,问题仍未解决。
相关代码
C++服务器核心代码
// 示例代码,替换为实际业务代码 #include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); std::string json_data = "{\"data\": \"sample\"}"; // 创建socket文件描述符 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置socket复用选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); // 绑定端口 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } while(true) { if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // 构造响应 std::string response = "HTTP/1.1 200 OK\r\n"; response += "Content-Type: application/json\r\n"; response += "Access-Control-Allow-Origin: *\r\n"; response += "\r\n"; response += json_data; send(new_socket, response.c_str(), response.length(), 0); close(new_socket); } return 0; }
React请求代码
// 示例代码,替换为实际业务代码 import { useEffect } from 'react'; function App() { useEffect(() => { const fetchData = async () => { try { console.log('Trying to fetch data from http://localhost:8080/simdata'); const response = await fetch('http://localhost:8080/simdata'); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } }; fetchData(); }, []); return <div>Data Fetch Test</div>; } export default App;
解决方案
1. 调整Electron主进程网络安全配置
Electron默认Web安全策略可能拦截localhost请求,可在主进程中修改配置:
const { app, BrowserWindow } = require('electron'); function createWindow() { const mainWindow = new BrowserWindow({ webPreferences: { // 临时关闭Web安全(仅测试用,生产环境建议用严格CSP) webSecurity: false, // 或配置精准内容安全策略,允许访问目标端口 // contentSecurityPolicy: "connect-src 'self' http://localhost:8080 http://127.0.0.1:8080;" } }); mainWindow.loadURL('http://localhost:3000'); // React开发服务器地址 } app.whenReady().then(createWindow);
2. 修复C++服务器连接处理逻辑
确保服务器完整处理HTTP请求生命周期:
- 读取完整的客户端请求(避免未读数据导致连接异常)
- 发送完整的响应头部(含CORS和连接管理字段)
- 响应后正确关闭连接
修改后的C++服务器响应逻辑示例:
// 先读取客户端请求内容,避免连接阻塞 char buffer[1024] = {0}; read(new_socket, buffer, 1024); // 构造完整响应 std::string response = "HTTP/1.1 200 OK\r\n"; response += "Content-Type: application/json\r\n"; response += "Access-Control-Allow-Origin: *\r\n"; response += "Access-Control-Allow-Methods: GET, OPTIONS\r\n"; response += "Access-Control-Allow-Headers: Content-Type\r\n"; response += "Connection: close\r\n"; // 明确关闭连接 response += "\r\n"; response += json_data; send(new_socket, response.c_str(), response.size(), 0); shutdown(new_socket, SHUT_RDWR); // 先关闭读写再释放socket close(new_socket);
3. 禁用Electron代理设置
系统代理可能拦截localhost请求,在主进程中添加:
app.commandLine.appendSwitch('no-proxy-server');
4. 验证服务器绑定地址
确保C++服务器绑定到0.0.0.0(而非仅127.0.0.1),允许所有网络接口访问:
address.sin_addr.s_addr = INADDR_ANY;
内容的提问来源于stack exchange,提问作者H 1
相关产品推荐
相关产品推荐

