0

I am creating a program where I am trying to connect a server and multiple clients through a socket system. For some reason when I deserialize I get an exception.

I made it so that the first 2 bytes of the first message contains the length of the message that is coming. (This is so that I can receive messages bigger then the buffer (1024 bytes)). And the mistake I have has probably to do with this code?

Exception:

System.Runtime.Serialization.SerializationException: 'Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.'

The base send code is as following:

    public void Send(byte[] data)
    {
        if (ClientSocket != null && ClientSocket.Connected)
        {
            ClientSocket.BeginSend(AddSize(data), 0, data.Length, 0, ResponseSend, this);
        }
        else
        {
            ConnectionFailed();
        }
    }

    private byte[] AddSize(byte[] data)
    {
        var newData = BitConverter.GetBytes(Convert.ToUInt16(data.Length));
        Array.Resize(ref newData, sizeof(ushort) + data.Length);
        Array.Copy(data, 0, newData, sizeof(ushort), data.Length);
        return newData;
    }

    private void ResponseSend(IAsyncResult ar)
    {
        try
        {
            // Complete sending the data to the remote device.  
            var bytesSent = ClientSocket.EndSend(ar);
            SendCompleted();
        }
        catch (SocketException ex)
        {
            ConnectionFailed();
        }
    }

The base receive code is as following:

    private const int BufferSize = 1024;

    // Receive buffer.  
    private MemoryStream _bufferStream = new MemoryStream();
    private readonly byte[] _buffer = new byte[BufferSize];
    private ushort _messageLength;

    public void Receive()
    {
        if (ClientSocket != null && ClientSocket.Connected)
        {
            ClientSocket.BeginReceive(_buffer, 0, BufferSize, SocketFlags.None, ReceiveCommand, this);
        }
        else
        {
            ConnectionFailed();
        }
    }

    private void ReceiveCommand(IAsyncResult ar)
    {
        // Retrieve the socket from the state object.  
        var client = (BaseClient)ar.AsyncState;

        try
        {
            var bytesRead = ClientSocket.EndReceive(ar);
            if (bytesRead <= 0)
            {
                ConnectionFailed();
                return;
            }

            var messageSizeOffset = 0;
            if (_messageLength == 0)
            {
                _messageLength = GetMessageLength(client._buffer);
                messageSizeOffset = sizeof(ushort);
            }

            _bufferStream.Write(client._buffer, messageSizeOffset, bytesRead - messageSizeOffset);

            if (_bufferStream.Length >= _messageLength)
            {
                var data = Deserialize(_bufferStream);

                //Cleanup
                _messageLength = 0;
                _bufferStream.Dispose();
                _bufferStream = new MemoryStream();

                ReceiveCompleted(data);
            }

            Receive();
        }
        catch (SocketException ex)
        {
            ConnectionFailed();
        }
    }

And I just use this simple serialize and deserialize functions:

    private byte[] Serialize(object item)
    {
        MemoryStream stream = new MemoryStream();
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, item);
        return stream.ToArray();
    }

    public static object Deserialize(MemoryStream stream)
    {
        var binaryFormatter = new BinaryFormatter();
        stream.Seek(0, SeekOrigin.Begin);
        return binaryFormatter.Deserialize(stream);
    }

Does anybody has any idea why I get this error? Because I have no clue anymore.

I also added a sample on the following link: https://github.com/kevingoos/SocketTest

2
  • prolly you should set position after writing Commented Oct 8, 2019 at 8:34
  • @500-InternalServerError Your first solution with the data.length is the solution, stuppid mistake on my end. If you post this I will set it as solved! Commented Oct 8, 2019 at 11:40

1 Answer 1

1

Here in Send:

public void Send(byte[] data)
    {
        if (ClientSocket != null && ClientSocket.Connected)
        {
            ClientSocket.BeginSend(AddSize(data), 0, data.Length, 0, ResponseSend, this);
        }
        else
        {
            ConnectionFailed();
        }
    }

you send data.Length bytes out, but the AddSize() methods adds a ushort message-length field at the beginning of the buffer. The size of this field must be included in what is sent out.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.