我正在尝试让客户端应用程序将'MessageObject'发送到服务器应用程序。
每次我尝试反序列化服务器上的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 ro ='的行上,抛出OutOfMemoryException。我不明白这是怎么发生的,特别是考虑到我发送的对象很小。
我应该指出,我是通过网络发送序列化数据的新手,所以我可能在这方面做错了。
如果您需要澄清任何内容,请发表评论。 :)
谢谢。
编辑:按要求堆叠异常跟踪:
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.ReadObjectWithMap(System.Runtime.Serialization.Formatters.Binary.BinaryHeaderEnum binaryHeaderEnum)+ 0x38字节
mscorlib.dll中!System.Runtime.Serialization.Formatters.Binary。 _BinaryParser.Run() + 0x304字节
mscorlib.dll中!System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(System.Runtime.Remoting.Messaging.HeaderHandler handler = null, System.Runtime.Serialization.Formatters.Binary .__ BinaryParser serParser,bool fCheck,bool isCrossAppDomain, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage = null)+ 0xaf字节
mscorlib.dll中!System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream serializationStream,System.Runtime.Remoting.Messaging.HeaderHandler handler,bool fCheck,bool isCrossAppDomain, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage)+ 0xcf bytes
mscorlib.dll中!System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream serializationStream)+ 0x10字节HolotypeTwo.dll!HolotypeTwo.Engine.CheckByteStringForRO(字节[] byteString = {byte [8192]})第34行+ 0x10字节C# HolotypeServer.exe!HolotypeServer.UnauthorisedPlayer.StartListening() 第27行+ 0x8字节C# mscorlib.dll中!System.Threading.ThreadHelper.ThreadStart_Context(对象 状态)+ 0x63字节
mscorlib.dll中!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback回调,对象 state,bool ignoreSyncCtx)+ 0xb0 bytes
mscorlib.dll中!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback回调,对象 状态)+ 0x2c字节
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()+ 0x44 字节
答案 0 :(得分:0)
您是否检查过您要反序列化的内容?由于代码中存在缺陷,您可能偶尔会在流中获取两个对象。如果在标记之前发生'e'字节,则CheckByteStringForRO方法最终可能会跳过其终止标记。为了正确捕捉这种情况,你的其他条件必须是:
else
{
tStringIndex = 0;
if (byteString[i] == TerminationString[tStringIndex])
{
tStringIndex++;
}
}
另外,为什么不只是制作一个对象的集合并序列化它而不是使用终止标记呢?