Сериализация и десериализация - C# (240557)

Узнай цену своей работы

Формулировка задачи:

Доброго вечера. Возникло странное непонимание принципов сериализации. Дело в том, что я не встречал достаточно подробных материалов по сериализации. Учебники посвящают этой теме обычно 3-10 страниц с основными определениями. Вот, какая возникла проблема. Если вкратце, то, почему же почему вот здесь:
BinaryFormatter fm = new BinaryFormatter();
fm.Serialize(tempStorage, Msg);
Message m = (Message)fm.Deserialize(tempStorage);
Возникает в последней строке следующее: System.Runtime.Serialization.SerializationException (Конец потока обнаружен до завершения разбора.) Если более обширно, то вот здесь:
[Serializable]
public abstract class Message
{
  public static void SendToSocket(Socket sock, Message Msg)
  {
    MemoryStream tempStorage = new MemoryStream();
    BinaryFormatter fm = new BinaryFormatter();
    fm.Serialize(tempStorage, Msg);
    long MessageLength = tempStorage.Length;
    MemoryStream sendBuffer = new MemoryStream();
    BinaryWriter bw = new BinaryWriter(sendBuffer);
    bw.Write(MessageLength); // 8 байт
    bw.Write(tempStorage.ToArray()); // ещё ~ 250 байт
 
    sock.Send(sendBuffer.ToArray());
 
    tempStorage.Close();
    bw.Close();
    sendBuffer.Close();
  }

  public static Message ReciveFromSocket(Socket sock)
  {
    MemoryStream tempStorage = new MemoryStream();
    byte[] buffer = new byte[sizeof(Int64)];
    BinaryFormatter fm = new BinaryFormatter();
    if (sock.Available < sizeof(Int64))
      return null;
 
    sock.Receive(buffer, sizeof(Int64), SocketFlags.None);
    Int64 MessageLength = 0;
    for (int i = 0; i < sizeof(Int64); ++i)
    {
      MessageLength += buffer[i] << i*8;  // получение длинны сообщения
    }
 
    int TotalSleep = 0;
    int Sleeping = 30;
    while (sock.Available < MessageLength)
    {
      Thread.Sleep(Sleeping);
      TotalSleep += Sleeping;
      if (TotalSleep > 3000)
      {
        throw new SocketException();
      }
    } 
 
    buffer = new byte[MessageLength];
    sock.Receive(buffer, (int) MessageLength, SocketFlags.None);
    tempStorage.Write(buffer, 0, (int) MessageLength);
 
    Message M = (Message) fm.Deserialize(tempStorage);
    tempStorage.Close();
    return M;
}
Что я увидел под отладчиком: Метод SendToSocket: Сериализует сообщение. Корректно получает его длинну. Результирующий буффер получается точно такой, как и должен быть (длинна сериализованного объекта + sizeof(Int64)) Метод ReciveFromSocket: Корректно считывает первые 8 байт и получает в MessageLength именно ту цифру, которая и ожидалась (размер сериализованного объекта) После этого в буффере остаётся и читается из него ровно MessageLength байт. Из чего я сделал вывод, что это полное сообщение и больше ничего быть не должно. Однако, в строке Message M = (Message) fm.Deserialize(tempStorage); с завидной регулярностью появляется System.Runtime.Serialization.SerializationException (Конец потока обнаружен до завершения разбора.) Перед отправкой темы ещё раз посмотрел путь сообщения, посмотрел содержание sendBuffer.ToArray() в методе SendToSocket(), содержание buffer после получения сообщения в методе ReciveFromSocket(). Заканчиваются они одними и теми же байтами.

Решение задачи: «Сериализация и десериализация»

textual
Листинг программы
tempStorage.Position = 0;
Message m = (Message)fm.Deserialize(tempStorage);

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 4.286 из 5
Похожие ответы