C#对象转字节数组实现 TCP传输图片反序列化End of Stream报错问题
问题根因
你提供的对象和字节数组互转工具方法本身没有逻辑错误,报错的核心原因是TCP协议的流特性:
- 字符串序列化后的字节数组长度极小,单次TCP接收就能拿到完整数据,因此反序列化正常
- 图片序列化后的字节数组体积远大于字符串,发送端单次调用
Send发出的字节流,接收端需要多次调用Receive才能收全所有数据。你当前的逻辑是收到部分数据就直接传入反序列化方法,解析到一半没有后续数据,就会抛出End of Stream encountered before parsing was completed.错误。
修复方案
1. 传输层新增长度前缀规则
发送端和接收端约定固定规则:所有消息前加4字节的长度头,存储后续实际消息体的字节长度,避免粘包/半包问题。
2. 发送端逻辑改造示例
// 发送数据逻辑示例,假设tcpClient是已连接的TcpClient对象 public void SendObject(TcpClient tcpClient, object obj) { byte[] msgBytes = ObjectToByteArray(obj); byte[] lengthBytes = BitConverter.GetBytes(msgBytes.Length); NetworkStream stream = tcpClient.GetStream(); // 先发4字节长度头 stream.Write(lengthBytes, 0, lengthBytes.Length); // 再发实际消息体 stream.Write(msgBytes, 0, msgBytes.Length); }
3. 接收端逻辑改造示例
// 接收数据逻辑示例,假设tcpClient是已连接的TcpClient对象 public object ReceiveObject(TcpClient tcpClient) { NetworkStream stream = tcpClient.GetStream(); // 第一步:先收满4字节长度头 byte[] lengthBuffer = new byte[4]; int receivedLen = 0; while(receivedLen < 4) { int read = stream.Read(lengthBuffer, receivedLen, 4 - receivedLen); if(read == 0) throw new Exception("连接已断开"); receivedLen += read; } int msgTotalLen = BitConverter.ToInt32(lengthBuffer, 0); // 第二步:收满指定长度的完整消息体 byte[] msgBuffer = new byte[msgTotalLen]; receivedLen = 0; while(receivedLen < msgTotalLen) { int read = stream.Read(msgBuffer, receivedLen, msgTotalLen - receivedLen); if(read == 0) throw new Exception("连接已断开"); receivedLen += read; } // 第三步:用完整的字节数组反序列化 return ByteArrayToObject(msgBuffer); }
注意事项
BinaryFormatter本身存在严重的安全风险,反序列化不可信的外部传入数据可能导致任意代码执行,如果你的聊天系统需要对外开放,建议替换为更安全的序列化方案,比如System.Text.Json、MessagePack等。
内容的提问来源于stack exchange,提问作者GHOST
相关产品推荐
相关产品推荐

