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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 23:39:01