You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在React中如何建立普通TCP Socket连接接收服务器数据(非WebSocket)

核心限制说明

浏览器环境下运行的前端JavaScript没有直接创建普通TCP连接的权限,仅支持HTTP、WebSocket等浏览器规范内的网络协议。你用的socket.io-client是基于WebSocket封装的库,只能对接实现了WebSocket/HTTP协议的服务端,无法直接连接裸TCP端口的netcat服务,所以你当前的代码无法达成需求。

可用解决方案

分两种使用场景提供可行方案:


场景1:React应用运行在普通浏览器中

需要额外部署一个Node.js中转代理服务,代理侧对接裸TCP服务,再通过WebSocket和前端通信:

  1. 首先编写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()
  })
})
  1. 修改你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 03:06:03