Search code examples
c#socketsasynchronousbinaryformatter

Using Binary Formatter with asynchronous sockets


I am trying to utilize the benefits of asynchronous sockets in C# with serializing/deserializing with BinaryFormatter, but am running into serveral issues. Mainly, I keep getting the error:

No map for object 1953724755

when trying to deserialize the network stream.

I've tried changing to a synchronous socket, and that seems to work fine, but when using an asynchronous one (with BeginRecieve and EndRecieve and such), I still get this error.

Here is the code where I am deserializing:

private void BeginDictionaryRecieve(IAsyncResult ar)
{
    Stream socketStream = new NetworkStream(socketState.workSocket);
    IFormatter dataFormatter = new BinaryFormatter();
    socketState.workSocket.EndReceive(ar);
    List<string> rackthatWasClicked = (List<string>) 
        dataFormatter.Deserialize(socketStream);
    this.recievedListForRackDisplay = rackthatWasClicked;
    OnDataRecieved.Invoke();
    socketState.workSocket.BeginReceive(socketState.buffer, 0, StateObject.BufferSize, 0,new AsyncCallback(BeginDictionaryRecieve), socketState);
}

And here is the serialization code (synchronous):

IPAddress ipAdd = IPAddress.Parse("127.0.0.1");
TcpClient myClient = new TcpClient();
myClient.Connect(ipAdd, 8002);
Stream clientStream = myClient.GetStream();
IFormatter f = new BinaryFormatter();
f.Serialize(clientStream, ShelfDataToSend);
clientStream.Dispose();
myClient.Dispose();

I should note that I am using BinaryFormatter because I can't seem to find a way to serialize an object other than a string with normal .Write operations on a socket.


Solution

  • Thanks to the direction from Hans, I was able to find a solution that works nicely. I'm now receiving data like this:

    try
    {
        StateObject state = (StateObject) ar.AsyncState;
        Socket client = state.workSocket;
    
        int bytesRead = client.EndReceive(ar);
    
        if (bytesRead > 0)
        {
            stream.Write(state.buffer, 0, bytesRead);
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(BeginDictionaryRecieve), state);
        }
        else
        {
            if (stream.Length > 1)
            {
                BinaryFormatter formatter = new BinaryFormatter();
                stream.Position = 0;
                this.recievedListForRackDisplay =(List<string>)formatter.Deserialize(stream);
                OnDataRecieved.Invoke();
    
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                                new AsyncCallback(BeginDictionaryRecieve), state);
            }
        }
    
    }
    catch (Exception e)
    {
        throw e;
    }
    

    It should also be noted that this solution only works if the client Socket is disposed of after sending its data.