【发布时间】:2013-06-29 20:31:00
【问题描述】:
我有客户端和服务器端应用程序的项目。当然,他们交换数据。我正在测试大型对象(大约 5 mb)的数据流并遇到了一个问题: 有时 BinaryFormatter Deserialize() 抛出这个异常:
二进制流“0”不包含有效的 BinaryHeader。可能的原因是无效的流或序列化和反序列化之间的对象版本更改。 ---(不一定是流“0”,但也可能是其他索引)。我检查了数据的大小(发送端和接收端),它们是相同的,但内容(字节的平均顺序与发送的数据包不同)。 代码来了:
public static ICommand Deserialize(byte[] bytes)
{
BinaryFormatter frmt=new BinaryFormatter();
frmt.AssemblyFormat = FormatterAssemblyStyle.Simple;
frmt.Binder=new BindingType();
using (MemoryStream ms = new MemoryStream(bytes))
{
ms.Seek(0, SeekOrigin.Begin);
return (ICommand)frmt.Deserialize(ms);
}
}
private class BindingType:SerializationBinder//for deserializeing object in assembly, different from where serialized
{
public override Type BindToType(string assemblyName, string typeName)
{
Type toDeserialize = null;
String exeAssembly = Assembly.GetExecutingAssembly().FullName;
if (typeName == "Server.ServerPlayer")
typeName = "Command_Entities.Player";
if (typeName == "Server.ServerLobby")
typeName = "Command_Entities.Lobby";
// The following line of code returns the type.
toDeserialize = Type.GetType(String.Format("{0}, {1}",typeName, exeAssembly));//change assembly name and type accordingly to object being deserialized
//to match current assembly name
return toDeserialize;
}
}
这是我的接收逻辑:
private void AsyncReceiveLoop(object obj)
{
byte[] metaData = new byte[4];
byte[] data = null;
int received = 0;
try
{
while (!_stop)
{
_me.Receive(metaData, 0, 4, SocketFlags.None);
_packetSize =Convert.ToInt32( BitConverter.ToUInt32(metaData, 0));
data = CorrectReceiver.Receive(_me, _packetSize).ToArray();
if (_packetSize == data.Length)
{
_mainCallback(data);
}
}
}
catch (SocketException ex)
{
_ecxeptionCallback(ex);
}
}
还有这个(CorrectReceiver):
public static byte[] Receive(Socket soc, int packetSize)
{
NetworkStream ns=new NetworkStream(soc,false);
List<byte> totalBytes=new List<byte>();
int receivedTotal = 0;
byte[] tempBytes=null;
int size = 0;
int received = 0;
int available = 0;
byte[] rec = null;
tempBytes = new byte[packetSize];
while (packetSize > receivedTotal)
{
if (ns.DataAvailable)
{
received=ns.Read(tempBytes, receivedTotal, packetSize-receivedTotal);
if(received==0)
throw new Exception("Connection closed...");//connection closed when 0 bytes received
receivedTotal += received;
}
else{ System.Threading.Thread.Sleep(50);}
}
return tempBytes;
}
您可能会在这里找到一些不必要或愚蠢的解决方案,但是这个问题持续了很长时间,并且我对代码和逻辑进行了很多更改。 所以如果你们中的任何人在这里看到了一些东西,这可能是问题的原因,或者如果有人过去遇到过这个问题,请帮助我找到错误。
【问题讨论】:
-
你说有时候字节顺序不对?如果是这样,那么您没有反序列化问题,而是通信问题。可能是当您读取长度时,您没有收到 4 个字节。如果发生这种情况,那么您收到的数据包的第一部分将是长度标头的一部分。您可能应该检查以确保在读取数据包大小时实际获得 4 个字节。
-
嗨,吉姆。谢谢您的回复。我解决了这个问题,问题出在线程中:我在 AsyncReceiveLoop 中切换线程并得到了这个奇怪的错误。在切换旧线程读取字节和新线程读取截断字节之间的某个时间点。应始终小心交叉线程。谢谢。
-
@GiorgiEgoTwinKhutsishvili 如果您解决了您的问题,您应该发布您的解决方案作为答案,然后接受它。
标签: c# serialization