Использование Binary Formatter с асинхронными сокетами - PullRequest
2 голосов
/ 24 мая 2019

Я пытаюсь использовать преимущества асинхронных сокетов в C # при сериализации / десериализации с помощью BinaryFormatter, но сталкиваюсь с несколькими проблемами.В основном я получаю сообщение об ошибке:

No map for object 1953724755

при попытке десериализации сетевого потока.

Я пытался перейти на синхронный сокет, и это, кажется, работает нормально, но при использовании асинхронного (с BeginRecieve, EndRecieve и т. Д.) Я все еще получаю эту ошибку.

Вот код, который я десериализирую:

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

А вот код сериализации (синхронно):

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();

Я должен отметить, что я используюBinaryFormatter, потому что я не могу найти способ сериализации объекта, кроме строки, с обычными операциями .Write на сокете.

1 Ответ

2 голосов
/ 24 мая 2019

Благодаря указаниям Ганса, я смог найти решение, которое прекрасно работает. Сейчас я получаю данные, подобные этим:

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

Следует также отметить, что это решение работает только в том случае, если клиентское гнездо утилизируется после отправки его данных.

...