2011-08-28 4 views
4

Я пытаюсь получить клиентское приложение для отправки MessageObject в серверное приложение.Deserialization using BinaryFormatter производит OutOfMemoryException

Каждый раз, когда я пытаюсь десериализовать MessageObject на сервере, я получаю исключение OutOfMemoryException.


Прежде всего, здесь MessageObject класс:

[Serializable] 
    public class MessageObject : ReplicableObject { 
     public string Command; 
     public string[] Parameters; 

     public MessageObject() { 

     } 

     public MessageObject(string command, string[] parameters) { 
      Command = command.ToLower(); 
      Parameters = parameters; 
     } 
    } 

MessageObject является дочерним ReplicableObject. Вот ReplicableObject:

[Serializable] 
    public abstract class ReplicableObject { 
     public string UniqueID { 
      get { 
       if (uniqueID == "" || uniqueID == null) { 
        uniqueID = DateTime.Now.Subtract(new DateTime(1990, 1, 1)).TotalMilliseconds.ToString(); 
        uniqueID = uniqueID.Substring(uniqueID.Length/2) + Engine.Random(1000000, 9999999).ToString(); 
       } 
       return uniqueID; 
      } 
      private set { uniqueID = value; } 
     } 
     private string uniqueID; 

     [NonSerialized] 
     public bool RequiresReplication = true; 

     public ReplicableObject() { 
      uniqueID = DateTime.Now.Subtract(new DateTime(1990, 1, 1)).TotalMilliseconds.ToString(); 
      uniqueID = uniqueID.Substring(uniqueID.Length/2) + Engine.Random(1000000, 9999999).ToString(); 
     } 
    } 

Когда клиент готов отправить MessageObject на сервер, это код, он использует:

public static void SerializeRO(Stream stream, ReplicableObject ro) { 
      Formatter.Serialize(stream, ro); 
      stream.Write(ASCIIEncoding.ASCII.GetBytes("endhtobject"), 0, 11); 
     } 

TerminationString является:

public static byte[] TerminationString = ASCIIEncoding.ASCII.GetBytes("endhtobject"); 

Как только сервер получает данные, этот метод вызывается (здесь вызывается исключение):

public static ReplicableObject CheckByteStringForRO(byte[] byteString) { 
      int tStringIndex = 0; 
      for (int i = 0; i < byteString.Length; ++i) { 
       if (byteString[i] == TerminationString[tStringIndex]) { 
        ++tStringIndex; 
        if (tStringIndex >= TerminationString.Length) { 
         MemoryStream ms = new MemoryStream(); 
         ms.Write(byteString, 0, i - 10); 
         ms.Position = 0; 
         ReplicableObject ro = (ReplicableObject) Formatter.Deserialize(ms); 
         ms.Close(); 
         return ro; 
        } 
       } 
       else tStringIndex = 0; 
      } 
      return null; 
     } 

Большая часть описанного выше способа, просто ищет TerminationString, поэтому здесь важные строки:

MemoryStream ms = new MemoryStream(); 
          ms.Write(byteString, 0, i - 10); 
          ms.Position = 0; 
          ReplicableObject ro = (ReplicableObject) Formatter.Deserialize(ms); 
          ms.Close(); 
          return ro; 

На линии, которая начинается «ReplicableObject ро =», то OutOfMemoryException является выброшены. Я не понимаю, как это может произойти, особенно учитывая, что объекты, которые я отправляю, являются крошечными.

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

Оставьте комментарий, если вам нужно уточнить что-либо. :)

спасибо.


Edit: трассировка стека исключения по запросу:

mscorlib.dll System.Runtime.Serialization.Formatters.Binary.BinaryObjectWithMap.Read (System.Runtime.Serialization.Formatters.Binary!. _ BinaryParser вход = {System.Runtime.Serialization.Formatters.Binary. _BinaryParser}) + 0x4F байт
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary._ BinaryParser.ReadObjec tWithMap (System.Runtime.Serialization.Formatters.Binary.BinaryHeaderEnum binaryHeaderEnum) + 0x38 байтов
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary.
_BinaryParser.Run() + 0x304 bytes
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize (System.Runtime.Remoting.Messaging.HeaderHandler Обработчик = нуль, System.Runtime.Serialization.Formatters.Binary .__ BinaryParser serParser, BOOL fCheck, BOOL isCrossAppDomain, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage = нуль) + 0xAF байт
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler обработчик, BOOL fCheck, BOOL isCrossAppDomain, System.Runtime. Remoting.Messaging.IMethodCallMessage methodCallMessage) + 0xcf bytes
mscorlib.dll! System.Runtime.Serial ization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) + 0x10 байт

HolotypeTwo.dll! HolotypeTwo.Engine.CheckByteStringForRO (байт [] байтовой строки = {байт [8192]}) Строка 34 + 0x10 байт C# HolotypeServer.exe! HolotypeServer.UnauthorisedPlayer.StartListening() Line 27 + 0x8 байт C# mscorlib.dll! System.Threading.ThreadHelper.ThreadStart_Context (объект состояние) + 0x63 байт
mscorlib.dll ! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executeContext, System.Threading.Contex tCallback обратного вызова, объект состояние, BOOL ignoreSyncCtx) + 0xb0 байт
mscorlib.dll! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext ExecutionContext, System.Threading.ContextCallback обратного вызова, объект состояние) + 0x2c байт
mscorlib.dll! System.Threading.ThreadHelper.ThreadStart() + 0x44 байт

+0

Опубликовать трассировку стека исключения –

+0

Выполнено, я думаю ... – Xenoprimate

+0

Для начала не записывайте в memystream, используйте конструктор, который принимает байт [] в качестве аргумента. Это одна очевидная ошибка. –

ответ

0

вы проверили содержание того, что вы пытаетесь Deserialize? Из-за недостатка кода вы могли бы получать два объекта в потоке. Метод CheckByteStringForRO может закончиться тем, что пропустил свой маркер окончания, если байты «e» появляются непосредственно перед маркером. Для того, чтобы правильно уловить тот случай, ваше другое условие должно быть:

else 
{ 
    tStringIndex = 0; 

    if (byteString[i] == TerminationString[tStringIndex]) 
    { 
     tStringIndex++; 
    } 
} 

Кроме того, почему бы не просто сделать коллекцию своих объектов и сериализации, что вместо того, чтобы использовать маркеры терминации и все, что?