C#二进制格式化程序序列化和反序列化-3个随机例外 [英] C# Binary Formatter Serialization & Deserialization - 3 Random Exceptions

查看:271
本文介绍了C#二进制格式化程序序列化和反序列化-3个随机例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm creating a C# application (Client & Server). They're seperate projects and both reference a DLL that can serialize and deserialize any object that is inputed into them.

一切正常,直到我开始使用实时桌面监控(视频效果)。 DLL包含一个自定义屏幕截图 类,该类采用位图&将其写入该类的公共内存流。这是完成的全部过程:

Everything is working fine, until I start working with live desktop monitoring (Video-ish). The DLL contains a custom "Screenshot" class that takes in a bitmap & writes it to the public memorystream for that class. Here is how it is all done:


  1. 客户端按钮获取整个屏幕的屏幕截图(作为位图)

  2. 客户端构造一个 Screenshot 对象,对其进行序列化,然后将其发送到服务器。 (序列化将其转换为字节),然后客户端重复这些步骤以不断发送屏幕截图

  3. 服务器接收到这些字节,对其进行反序列化,检查其是否为 Screenshot 类型,然后引发一个事件&

  1. Client button takes screenshot of whole screen (as a bitmap)
  2. Client constructs a Screenshot object, serializes it, and sends it off to the server. (Serializing it turns it into bytes) Client then repeats these steps to constantly send screenshots
  3. Server receives these bytes, deserializes it, checks if it's a Screenshot type, then raises an event & displays this image on the form if true.






是的,我确实收到了实时图像提要,并且它会显示在表单上,​​但这只能持续3到10秒钟。我总共收到3个异常,它们是从客户端随机发生的。


Yes I do receive a live image feed and it's displayed on the form, but this only works for like 3 to 10 seconds. I'm getting 3 exceptions in all, they occur randomly from the clients.

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

I'll post the screenshots with some details about them too, excuse the weird exception handler box. https://imgur.com/a/Uv4r6wY

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

Here is the Serialize and Deserialize code inside the 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);
        }
    }

我一直在花费大量时间研究这些错误,一无所有,我似乎应用的任何东西都会引起另一个错误。

I've been spending hours researching these errors and come up with nothing, anything that I seem to apply creates another error.

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

Thank you for taking your time to analyze my messy code. Really ty.

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

If you're curious on how the server handles the received data:

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


推荐答案

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

The serialization exceptions simply mean that the data is somehow incomplete or damaged. The issue lies with your data transmission, not your serialization.

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

I'm assuming you're using a TCP socket for the connection? There is no guarantee that a read call on a Socket (or TcpClient, Stream etc.) gives you all the data you expect at once. The buffer is filled with up to size number of bytes, from the data that is currently available on the receiving side. Especially when sending large amounts of data over a network, it is likely to arrive in multiple partial packets rather than all at the same time. Also, a single receive call may return both the end of the current message and the beginning of the next.

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

You need to repeatedly call BeginReceive in a loop until you know you have the complete message, e.g. by manually prefixing the transmitted data with a length value on the sending side and then waiting until you have buffered at least that amount of data on the receiving side.

这篇关于C#二进制格式化程序序列化和反序列化-3个随机例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆