C# Socket广播数据时出现传输连接写入失败问题求助
C# TCP服务端向前端广播数据报错及前端无接收问题排查与修复
核心问题分析
Connected属性判断失效:Socket.Connected仅反映最近一次IO操作的状态,连接断开后不会自动更新,导致循环继续尝试发送数据触发错误。- TCP数据边界未定义:直接发送原始JSON字节流,前端无法区分完整的消息单元,无法正确解析数据,进而主动断开连接,引发"连接被中止"的错误。
- 资源未正确清理:发送异常后未关闭连接和流,导致资源泄漏;代码中
socketInformation为未定义变量,属于语法错误。
修复方案与代码调整
1. 定义消息边界,解决TCP粘包问题
在每个JSON消息前添加消息长度(4字节的Int32),让前端先读取长度,再读取对应长度的字节,确保能解析完整消息。
2. 替换不可靠的Connected判断,改用IO操作结果检测连接状态
通过发送/接收操作的返回值或异常来判断连接是否有效,而非依赖Connected属性。
3. 修正代码错误,完善资源清理
- 替换未定义的
socketInformation为socket; - 使用
using语句自动管理NetworkStream和Socket资源; - 发送异常后立即终止循环并清理连接。
修改后的完整代码
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; class TcpBroadcaster { static void Main() { Socket listenerSocket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); listenerSocket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 15001)); listenerSocket.Listen(10); listenerSocket.SendTimeout = 5000; listenerSocket.ReceiveTimeout = 5000; listenerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); listenerSocket.NoDelay = true; Console.WriteLine("Waiting for Connection ....."); while (true) { // 等待新连接 using Socket acceptedConnection = listenerSocket.Accept(); using NetworkStream stream = new NetworkStream(acceptedConnection); Console.WriteLine("Client connected. Starting transmission..."); bool isConnected = true; while (isConnected) { Console.WriteLine("Transmitting Feed .."); try { // 准备JSON数据 string jsonContent = PrepareMarkertDataToJSON(data); // 假设data是你的数据源 byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonContent); // 先发送消息长度(4字节,大端格式适配多数前端) byte[] lengthBytes = BitConverter.GetBytes(jsonBytes.Length); if (!BitConverter.IsLittleEndian) { Array.Reverse(lengthBytes); } stream.Write(lengthBytes, 0, lengthBytes.Length); // 发送JSON数据 stream.Write(jsonBytes, 0, jsonBytes.Length); stream.Flush(); // 确保数据写入网络 Thread.Sleep(1000); } catch (SocketException ex) { Console.WriteLine($"Connection error: {ex.Message}"); isConnected = false; } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); isConnected = false; } } Console.WriteLine("Client disconnected. Waiting for new connection..."); } } // 模拟数据序列化方法,替换为你的实际逻辑 static string PrepareMarkertDataToJSON(object data) { return "{\"data\": \"sample market data\"}"; } }
前端适配要点
前端接收数据时,需要先读取4字节的长度,再读取对应长度的字节,再转为JSON(Node.js TCP客户端示例):
const net = require('net'); const client = net.connect({ port: 15001, host: '127.0.0.1' }, () => { console.log('connected to server'); }); let buffer = Buffer.alloc(0); client.on('data', (data) => { buffer = Buffer.concat([buffer, data]); // 循环处理完整消息 while (buffer.length >= 4) { const length = buffer.readInt32BE(0); // 和后端大端格式对应 if (buffer.length >= 4 + length) { const jsonBuffer = buffer.slice(4, 4 + length); const json = JSON.parse(jsonBuffer.toString('utf8')); console.log('Received data:', json); // 截断buffer,处理剩余数据 buffer = buffer.slice(4 + length); } else { break; // 数据不足,等待下一次接收 } } }); client.on('end', () => { console.log('disconnected from server'); });
额外注意事项
- 若前端使用WebSocket而非原生TCP,建议后端直接使用ASP.NET Core WebSocket服务,避免手动处理TCP消息边界;
- 超时时间设置无需过大,5秒左右足够,过长会导致无效连接占用资源;
- 生产环境建议使用异步IO(
AcceptAsync、WriteAsync),避免阻塞主线程。
内容的提问来源于stack exchange,提问作者Kinyua James
相关产品推荐
相关产品推荐

