Сериализация и десериализация - 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);