C#二进制格式化程序序列化和反序列化-3个随机异常

时间:2019-03-03 19:37:46

标签: c# serialization deserialization

我正在创建一个C#应用程序(客户端和服务器)。它们是单独的项目,并且都引用了一个DLL,该DLL可以序列化和反序列化输入到其中的任何对象。

一切正常,直到我开始使用实时桌面监控(Video-ish)。 DLL包含一个自定义的“屏幕快照” 类,该类接受一个位图并将其写入该类的公共内存流中。这是所有步骤:

  1. “客户端”按钮获取整个屏幕的屏幕截图(作为位图)
  2. 客户端构造一个 Screenshot 对象,对其进行序列化,然后将其发送到服务器。 (序列化将其转换为字节),然后客户端重复这些步骤以不断发送屏幕截图
  3. 服务器接收这些字节,对其进行反序列化,检查其是否为 Screenshot 类型,然后引发事件并在表单上显示此图像(如果为true)。

是的,我确实收到了实时图像供稿,并在表单上显示了它,但这仅能工作3到10秒钟。我总共收到3个例外,它们是从客户端随机发生的。

我还将张贴有关屏幕快照的一些详细信息,请原谅怪异的异常处理程序框。 https://imgur.com/a/Uv4r6wY


这是DLL中的序列化和反序列化代码:

    public static byte[] Serialize(Object paramObj)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(ms, paramObj);
            return ms.ToArray();
        }
    }
    public static Object Deserialize(byte[] paramBuffer)
    {
        using (MemoryStream ms = new MemoryStream(paramBuffer))
        {
            BinaryFormatter bf = new BinaryFormatter();
            //ms.Position = 0;
            ms.Seek(0, SeekOrigin.Begin);
            return (Object)bf.Deserialize(ms);
        }
    }

我一直在花费大量时间研究这些错误,却一无所获,似乎应用的任何事情都会导致另一个错误。

感谢您抽出宝贵的时间来分析我的凌乱代码。是真的。


如果您对服务器如何处理接收到的数据感到好奇:

    public void receiveAll()
    {
        byte[] _buffer = new byte[55000];

        _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _clientSocket);

        void ReceiveCallback(IAsyncResult AR)
        {
            try
            {
                _clientSocket = (Socket)AR.AsyncState;
                int received = _clientSocket.EndReceive(AR);
                byte[] receivedbuffer = new byte[received];
                Array.Copy(_buffer, receivedbuffer, received);

                // The "ObjectHandler" is the class to Ser & Deser in the DLL
                Object data = ObjectHandler.Deserialize(receivedbuffer);

                try 
                {
                    // Check the data that is received & determine type
                }
                catch (Exception ex)
                {
                     // Show Exception box
                }

                // Repeat the receive process...
                _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _clientSocket);
            }
            catch (Exception ex)
            {
                RemoveClient();
                // Show Exception box
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

序列化异常仅表示数据不完整或已损坏。问题出在您的数据传输,而不是序列化。

我假设您正在使用TCP套接字进行连接?无法保证对Socket(或TcpClientStream等)的读取调用会立即为您提供所有期望的数据。根据接收端当前可用的数据,缓冲区中最多填充 size个字节。尤其是在通过网络发送大量数据时,它有可能到达多个部分数据包,而不是同时到达。同样,单个接收呼叫可能会同时返回当前消息的末尾和下一条消息的开始。

您需要循环调用BeginReceive直到知道完整的消息,例如通过在发送方手动为传输的数据添加长度值作为前缀,然后等待直到在接收方至少缓冲了该数量的数据。