Разочаровывающее исключение сериализации TCP: двоичный поток '0' не содержит допустимого BinaryHeader - PullRequest
1 голос
/ 31 августа 2010

Я разместил вопрос на , как отправлять большие объекты по 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;
        }
    }
}

Остальная часть кода относится к этому примеру.можно найти в моем оригинальном вопросе .

Кто-нибудь знает, что вызывает это исключение и как я могу его избежать?

Обновление

ИзмененоRead для чтения максимум _tcpClient.ReceiveBufferSize байт за раз, вместо того, чтобы пытаться прочитать полный размер сообщения (который может быть больше, чем размер буфера), и хотя частота исключения немного уменьшилась, это все еще происходит довольно часто.

Ответы [ 2 ]

3 голосов
/ 31 августа 2010

Позвольте мне предложить вам небольшое упрощение вашего кода:

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 для передачи объектов по проводам.

0 голосов
/ 02 июня 2011

WCF не так хорош в клиент-сервере. Опрос дуплекса - довольно сырая технология.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...