-1

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.

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

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.

I'll post the screenshots with some details about them too, excuse the weird exception handler box. https://i.sstatic.net/gXwab.jpg


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

1 Answer 1

2

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

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.

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.

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

2 Comments

How would I be able to wire up the transmitted data with the length of itself if it is only serializing an object? Which makes me more confused on how the server will determine that length without already deserializing it... But I do understand the concept of what you mean & it clears up my head more. I just somehow need to implement it
You know how long the serialized data is after writing it to the MemoryStream on the sending side. You can send that value before sending the data itself.

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.