令人沮丧的TCP序列化异常:二进制流“0”不包含有效的BinaryHeader

时间:2010-08-31 06:23:46

标签: c# sockets serialization tcp

我在how to send large objects over TCP发布了一个问题,似乎主要问题已经解决,但现在经常我得到另一个例外:

  

二进制流'0'不包含   有效的BinaryHeader。可能的原因   是无效的流或对象版本   序列化和。之间的变化   反序列化。

问题仍在我的接收方法中:

public Message Receive()
{
    if (_tcpClient == null || !_tcpClient.Connected)
    {
        throw new TransportException("Client Not Connected");
    }

    // buffers
    byte[] msgBuffer;
    byte[] sizeBuffer = new byte[sizeof(int)];

    // bites read
    int readSize = 0;
    // message size
    int size = 0;

    MemoryStream memStream = new MemoryStream();
    NetworkStream netStream = _tcpClient.GetStream();
    BinaryFormatter formatter = new BinaryFormatter();
    try
    {
        // Read the message length
        netStream.Read(sizeBuffer, 0, sizeof(int));

        // Extract the message length
        size = BitConverter.ToInt32(sizeBuffer, 0);
        msgBuffer = new byte[size];

        // Fill up the message msgBuffer
        do
        {
            // Clear the buffer
            Array.Clear(msgBuffer, 0, size);

            // Read the message
            readSize += netStream.Read(msgBuffer, 0, _tcpClient.ReceiveBufferSize);

            // Write the msgBuffer to the memory streamvb
            memStream.Write(msgBuffer, 0, readSize);

        } while (readSize < size);

        // Reset the memory stream position
        memStream.Position = 0;

        // Deserialize the message
        return (Message)formatter.Deserialize(memStream); // <-- Exception here

    }
    catch (System.Exception e)
    {
        if (_tcpClient == null || !_tcpClient.Connected)
        {
            throw new TransportException("Client Not Connected");
        }
        else
        {
            throw e;
        }
    }
}

可以在我的original question中找到与此示例相关的其余代码。

有人知道造成这种异常的原因以及如何避免它吗?

更新

Read更改为一次读取最多_tcpClient.ReceiveBufferSize个字节,而不是尝试读取完整的邮件大小(可能大于缓冲区大小)以及例外情况略有下降,但仍然经常发生。

2 个答案:

答案 0 :(得分:3)

让我建议您稍微简化一下代码:

public Message Receive()
{
    try
    {
        if (_tcpClient == null || !_tcpClient.Connected)
        {
            throw new TransportException("Client Not Connected");
        }

        using (var stream = _tcpClient.GetStream())
        using (var reader = new BinaryReader(stream))
        {
            int size = reader.ReadInt32();
            byte[] buffer = reader.ReadBytes(size);
            using (var memStream = new MemoryStream(buffer))
            {
                var formatter = new BinaryFormatter();
                return (Message)formatter.Deserialize(memStream);
            }
        }
    }
    catch (System.Exception e)
    {
        if (_tcpClient == null || !_tcpClient.Connected)
        {
            throw new TransportException("Client Not Connected");
        }
        throw e;
    }
}

另外,如果你这样做是为了娱乐和/或教育目的,那么没关系,但在一个真实的项目中你应该考虑WCF,以便通过网络传输对象。

答案 1 :(得分:0)

WCF在客户端 - 服务器上不太好。轮询双工是一项非常原始的技术。