首页 > 解决方案 > 反序列化通过套接字发送的消息时出现 SerializationException

问题描述

我正在创建一个程序,我试图通过套接字系统连接服务器和多个客户端。出于某种原因,当我反序列化时出现异常。

我这样做是为了使第一条消息的前 2 个字节包含即将到来的消息的长度。(这样我可以接收比缓冲区更大的消息(1024 字节))。我的错误可能与这段代码有关?

例外:

System.Runtime.Serialization.SerializationException:“二进制流“0”不包含有效的 BinaryHeader。可能的原因是无效的流或序列化和反序列化之间的对象版本更改。

基本发送代码如下:

    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();
        }
    }

基本接收代码如下:

    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();
        }
    }

我只是使用这个简单的序列化和反序列化函数:

    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);
    }

有人知道我为什么会收到此错误吗?因为我已经没有头绪了。

我还在以下链接上添加了一个示例:https ://github.com/kevingoos/SocketTest

标签: c#.netsocketsserialization

解决方案


在这里Send

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

您发送data.Length字节,但这些AddSize()方法ushort在缓冲区的开头添加了一个消息长度字段。该字段的大小必须包含在发送的内容中。


推荐阅读