在React中如何建立普通TCP Socket连接接收服务器数据(非WebSocket)
核心限制说明
浏览器环境下运行的前端JavaScript没有直接创建普通TCP连接的权限,仅支持HTTP、WebSocket等浏览器规范内的网络协议。你用的socket.io-client是基于WebSocket封装的库,只能对接实现了WebSocket/HTTP协议的服务端,无法直接连接裸TCP端口的netcat服务,所以你当前的代码无法达成需求。
可用解决方案
分两种使用场景提供可行方案:
场景1:React应用运行在普通浏览器中
需要额外部署一个Node.js中转代理服务,代理侧对接裸TCP服务,再通过WebSocket和前端通信:
- 首先编写Node.js代理服务代码,先执行依赖安装
npm install net ws:
const net = require('net') const WebSocket = require('ws') // 启动WebSocket服务,供前端连接 const wss = new WebSocket.Server({ port: 8080 }) wss.on('connection', (ws) => { // 连接netcat的TCP服务 const tcpClient = net.createConnection({ port: 3333, host: 'localhost' }, () => { console.log('已连接到TCP服务') }) // 接收TCP服务返回的内容,转发给前端 tcpClient.on('data', (data) => { ws.send(data.toString()) }) // TCP断开/错误时3秒自动重连 let reconnectTimer = null const reconnect = () => { reconnectTimer = setTimeout(() => { tcpClient.connect({ port: 3333, host: 'localhost' }) }, 3000) } tcpClient.on('end', reconnect) tcpClient.on('error', reconnect) // 前端断开时清理资源 ws.on('close', () => { clearTimeout(reconnectTimer) tcpClient.destroy() }) })
- 修改你的React前端代码,连接代理的WebSocket服务:
import React, { useState, useEffect, useRef } from 'react'; function App() { const [messageCount, setMessageCount] = useState(0); const wsRef = useRef(null); const reconnectTimerRef = useRef(null); const connect = () => { // 连接代理WebSocket服务 const ws = new WebSocket('ws://localhost:8080'); wsRef.current = ws; ws.onopen = () => { console.log('连接代理成功'); clearTimeout(reconnectTimerRef.current); }; // 接收代理转发的TCP数据 ws.onmessage = (e) => { // 这里e.data就是netcat返回的纯文本内容 setMessageCount(prev => prev + 1); }; // 断开/错误时3秒自动重连 ws.onclose = () => { reconnectTimerRef.current = setTimeout(connect, 3000); }; ws.onerror = () => { reconnectTimerRef.current = setTimeout(connect, 3000); }; }; useEffect(() => { connect(); // 组件卸载时清理资源 return () => { clearTimeout(reconnectTimerRef.current); wsRef.current?.close(); }; }, []); return ( <div className="theme-1"> <p>received {messageCount} messages</p> </div> ); } export default App;
另外你原有代码的useEffect存在闭包陷阱,要使用函数式更新setMessageCount(prev => prev + 1)才能正确累加计数,同时React中类名要使用className而不是class。
场景2:React应用是Electron/Tauri打包的桌面端应用
不需要中转代理,直接在框架的Node.js/后端侧调用原生TCP能力对接3333端口,再通过进程通信把数据传给React渲染层即可,自动重连逻辑可以直接在后端侧实现,稳定性更高。
内容的提问来源于stack exchange,提问作者freedo
相关产品推荐
相关产品推荐

