我写了一些代码,这是一个迷你简单模仿信使程序 . 在该计划;当用户注销时,我的LogOutCommand类的实例由客户端程序准备,序列化并发送到服务器 . 当服务器收到LogOutCommand时,它会反序列化并调用类的Execute方法,该方法执行db操作等 .
问题是,有时Server可以很好地反序列化,但有时会失败 . 据我所知,服务器有时会在完全准确地发送相关字节之前开始反序列化 .
如何使服务器以等待所有相关字节完成发送的方式启动反序列化?
或者您认为还有其他问题吗?
这是代码:
//服务器侦听套接字
private void ReadData(object obj)
{
Socket client = (Socket)obj;
while (true)
{
if (client.Available > 0)
{
byte[] buffer = new byte[client.Available];
client.Receive(buffer);
ServerCommandBase cmd = CommandReader.ReadSrvCommand(buffer);
cmd.Execute(context);
}
}
}
// CommandReader类
public class CommandReader
{
public static ServerCommandBase ReadSrvCommand(byte[] buffer)
{
return (ServerCommandBase)SerializationUtility.SerializationHelper.Deserialize(buffer);
}
public static ClientCommandBase ReadCliCommand(byte[] buffer)
{
return (ClientCommandBase)SerializationUtility.SerializationHelper.Deserialize(buffer);
}
}
//序列化/反序列化类
public class SerializationHelper {public static byte [] Serialize(object obj){BinaryFormatter formatter = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); try {formatter.Serialize(stream,obj); } catch(Exception){MessageBox.Show("Serialize Edilemiyor"); }
stream.Position = 0; return stream.ToArray(); }
public static object Deserialize(byte[] byteArr)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream ms = new MemoryStream(byteArr);
ms.Position = 0;
object retObj = null;
try
{
retObj = formatter.Deserialize(ms);
}
catch (Exception)
{
MessageBox.Show("Cannot Be Deserialized!");
}
return retObj;
}
}
2 回答
我认为这个问题是你试图在管道下来后立即反序列化数据 . 由于数据包如何通过网络发送,这可能是也可能是不可能的 .
您应该发送带有消息的标头,指示数据的长度(以字节为单位) . 然后接收字节,直到该数字被命中并反序列化然后才开始 .
您的 Headers 应该是特定的格式并具有特定的长度,以便在开头时很容易将其删除 .
首先,你不应该使用BinaryFormatter . 使用例如更好XmlSerializer的 .
其次,请包含您获得的异常详细信息 .