Сериализация и десериализация - C# (240557)
Формулировка задачи:
Доброго вечера. Возникло странное непонимание принципов сериализации. Дело в том, что я не встречал достаточно подробных материалов по сериализации. Учебники посвящают этой теме обычно 3-10 страниц с основными определениями. Вот, какая возникла проблема. Если вкратце, то, почему же почему вот здесь:
Возникает в последней строке следующее: System.Runtime.Serialization.SerializationException (Конец потока обнаружен до завершения разбора.)
Если более обширно, то вот здесь:
Что я увидел под отладчиком:
Метод SendToSocket:
Сериализует сообщение.
Корректно получает его длинну.
Результирующий буффер получается точно такой, как и должен быть (длинна сериализованного объекта + sizeof(Int64))
Метод ReciveFromSocket:
Корректно считывает первые 8 байт и получает в MessageLength именно ту цифру, которая и ожидалась (размер сериализованного объекта)
После этого в буффере остаётся и читается из него ровно MessageLength байт. Из чего я сделал вывод, что это полное сообщение и больше ничего быть не должно.
Однако, в строке
Message M = (Message) fm.Deserialize(tempStorage);
с завидной регулярностью появляется System.Runtime.Serialization.SerializationException (Конец потока обнаружен до завершения разбора.)
Перед отправкой темы ещё раз посмотрел путь сообщения, посмотрел содержание sendBuffer.ToArray() в методе SendToSocket(), содержание buffer после получения сообщения в методе ReciveFromSocket(). Заканчиваются они одними и теми же байтами.
BinaryFormatter fm = new BinaryFormatter(); fm.Serialize(tempStorage, Msg); Message m = (Message)fm.Deserialize(tempStorage);
[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; }
Решение задачи: «Сериализация и десериализация»
textual
Листинг программы
tempStorage.Position = 0; Message m = (Message)fm.Deserialize(tempStorage);
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д