【问题标题】:C# Binary Formatter Serialization & Deserialization - 3 Random ExceptionsC# 二进制格式化程序序列化和反序列化 - 3 个随机异常
【发布时间】:2019-03-03 19:37:45
【问题描述】:

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

一切正常,直到我开始使用实时桌面监控(视频)。 DLL 包含一个自定义的 "Screenshot" 类,该类接受位图并将其写入该类的公共内存流。这是如何完成的:

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

是的,我确实收到了实时图像提要,并且它显示在表单上,​​但这仅适用于 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
            }
        }
    }

【问题讨论】:

    标签: c# serialization deserialization


    【解决方案1】:

    序列化异常只是意味着数据不完整或损坏。问题在于您的数据传输,而不是您的序列化。

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

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

    【讨论】:

    • 如果只是序列化一个对象,我如何能够将传输的数据与自身的长度连接起来?这让我对服务器如何在没有反序列化它的情况下确定该长度感到更加困惑......但我确实理解你的意思的概念并且它更让我头脑清醒。我只是需要以某种方式实现它
    • 你知道序列化后的数据在发送端写入MemoryStream之后的时间。您可以在发送数据本身之前发送该值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2015-02-12
    • 2011-06-08
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多