反序列化报错“二进制流“0”不包含有效的 BinaryHeader。这可能是由于无效流,或由于在序列化和反序列化之间的对象版本更改。”

大光呢 2010-08-05 12:15:52
rt
问题是有时候报错,有时候正常。一半一半。数据发送和接收 没有问题的(所以代码没贴出来),数据长度和数据内容 完全一致。问题就在序列化和反序列化本身。
报错的类型是
有时候 : “二进制流“0”不包含有效的 BinaryHeader。这可能是由于无效流,或由于在序列化和反序列化之间的对象版本更改。”
有时候:“无法将位于索引42(这个索引不定)处的字节[FF](这个FF 每次都是)由指定的代码页转换为Unicode”。当我跟踪索引位置的内容时 发现,有时是 255(即FF,报错提示是对的),有的时候不是255(不是FF)。也就是说 这个提示不准确。

Server端 序列化代码

public byte[] getObjectBytes(object o)
{
try
{
#region//old Code
BinaryFormatter bf = new BinaryFormatter();
bf.TypeFormat = System.Runtime.Serialization.Formatters.FormatterTypeStyle.TypesWhenNeeded;
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, o);
ms.Position = 0;
return ms.GetBuffer();
#endregion
#region// new code
//MemoryStream ms = new MemoryStream();
//IFormatter formatter = new BinaryFormatter();
//formatter.Serialize(ms, o);
//byte[] bs = ms.GetBuffer();
//ms.Seek(0, SeekOrigin.Begin);
// return bs;
#endregion


}
catch { return null; }
}


Client 端 反序列化代码:

public DataSet getDataSet(byte[] getobjectBytes)
{
try
{
#region//old code
BinaryFormatter bf = new BinaryFormatter();
bf.TypeFormat = System.Runtime.Serialization.Formatters.FormatterTypeStyle.TypesWhenNeeded;
MemoryStream ms = new MemoryStream(getobjectBytes);
DataSet ds = (DataSet)bf.Deserialize(ms);
#endregion

#region//new code
//IFormatter formatter2 = new BinaryFormatter();
//MemoryStream ms2 = new MemoryStream();
//ms2.Write(getobjectBytes, 0, getobjectBytes.Length);
//ms2.Seek(0, SeekOrigin.Begin);
//DataSet ds = (DataSet )formatter2.Deserialize(ms2);
#endregion

return ds;
}
catch { return null; }
}


不管是用 Old Code 配合,还是New code 配合使用,都出现如上情况。

求解中。。。。。
...全文
2322 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
lishanya1 2011-05-28
  • 打赏
  • 举报
回复
我也碰到过这个问题 。。。尝试方法:你可以先把那些 反序列化的东西写入到文件里面 观察结果

还有听老师说 什么 。。传输的时候流刚好是相反的 。。因此要改变方向再进行反序列化 。。不过我也没实现过 。。只当可能的思路 。。。
大光呢 2010-08-10
  • 打赏
  • 举报
回复
我已经结贴了,怎么还可以跟啊?
大光呢 2010-08-09
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 yuwenge 的回复:]
反序列化不是问题。
问题是你序列化的时候是不是都对了。
[/Quote]
呵呵,有道理啊。我查查序列化的时候是不是有问题了。、
卧_槽 2010-08-09
  • 打赏
  • 举报
回复
反序列化不是问题。
问题是你序列化的时候是不是都对了。
大光呢 2010-08-09
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 ch5201314zt 的回复:]
TCP/IP协议不可能出现网络错误接收
客户端给服务器端发送数据的时候,如果数据比较大服务器端一次是接收不了的
得分几次接收 明白?
[/Quote]
这个 明白。
让偶不明白的是 错误时现时无。错误类型就是上面图片上展示的。我跟踪的结果表明 上面的错误提示是不准确的。
ch5201314zt 2010-08-09
  • 打赏
  • 举报
回复
TCP/IP协议不可能出现网络错误接收
客户端给服务器端发送数据的时候,如果数据比较大服务器端一次是接收不了的
得分几次接收 明白?
大光呢 2010-08-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 ch5201314zt 的回复:]
额,发送一条数据长度比较大的数据的时候你会发现,你在发送的数据长度,和你接受的数据长度是不一样的,
调试一下看看!在发送的时候加一个断点,在接受完毕加一个断点,看数据长度!
[/Quote]

你说的情况能出现,那是网络错误接收造成的。,我这里有检查过,还是能正常接收的啊。

你说的情况 是 网络接收出现异常的时候。我这里 已经把网络接收异常的状况 定义成错误了,不在往下执行。能执行到反序列化的数据,都是正确接收的数据。

大光呢 2010-08-09
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 oonukeoo 的回复:]
你多调试几次,注意报错时的一些操作问题,报错时你的接收缓冲区是否被正确赋值,发送端错误操作导致序列化时对象被错误赋值,你再接收后反序列化也能报这个错误。。。仔细看看吧,我也出现过类似的问题
[/Quote]

又跟踪了一下错误。catch 套try,两次捕获的错误类型不一致。还在检查,没找到错误根。
ch5201314zt 2010-08-09
  • 打赏
  • 举报
回复
额,发送一条数据长度比较大的数据的时候你会发现,你在发送的数据长度,和你接受的数据长度是不一样的,
调试一下看看!在发送的时候加一个断点,在接受完毕加一个断点,看数据长度!
大光呢 2010-08-09
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sp1234 的回复:]
好乱的代码,lz是写c++的吧?c#程序员不会写这么乱的socket代码吧!
[/Quote]
这话讲的,当心CPP的程序员来啐你啊
myhope88 2010-08-09
  • 打赏
  • 举报
回复
没弄过,帮顶下
大光呢 2010-08-09
  • 打赏
  • 举报
回复
最后查明,还是传输模块出了问题。
序列化和反序列化都没有问题。
之前报出的种种错误均是由网络传输数据错乱造成的。
现贴出 修改过的传输代码
Server端(发送代码)

#region//自动识别长度发送数据
public static int SendData(Socket socket, byte[] buffer, int outTime,string ForSendDataOnly)
{
if (socket == null || socket.Connected == false)
{
Log.WriteLog("参数socket 为null,或者未连接到远程计算机");
// throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == 0)
{
Log.WriteLog("参数buffer 为null ,或者长度为 0");
// throw new ArgumentException("参数buffer 为null ,或者长度为 0");
}

#region//自动识别并发送长度
int len = buffer.Length;
byte[] btLen = Encoding.UTF8.GetBytes(len.ToString()+"|");
byte[] btLenForSend = new byte[512];
btLen.CopyTo(btLenForSend, 0);
socket.Send(btLenForSend);


#endregion
int flag = 0;
try
{
int left = buffer.Length;
int sndLen = 0;
int curSendlen = 0;

while (true)
{
//if ((socket.Poll(outTime * 1000000, SelectMode.SelectWrite) == true))
//{
try
{
// 收集了足够多的传出数据后开始发送
curSendlen = socket.Send(buffer, sndLen, left, SocketFlags.None);
sndLen += curSendlen;
// left -= sndLen;
left -= curSendlen;
if (left == 0)
{ // 数据已经全部发送
flag = 0;
Ip.TCPtrance.Log.WriteControlText("【√】网络正确发送(flag = 0)" + " " + " 发送结果状态【" + flag.ToString() + "】 ", Form1.richTextBox1);
break;
}
else
{
if (curSendlen > 0)
{ // 数据部分已经被发送
continue;
}
else
{ // 发送数据发生错误
flag = -2;
break;
}
}
}
catch
{
flag = -1;
break;
}
//else
//{ // 超时退出
// flag = -1;
// break;
//}
}
}
catch (SocketException e)
{
Log.WriteLog(e);
flag = -3;
}
return flag;
}
#endregion

Client端(接收数据)

#region//自动识别长度接收数据
public static int temFlg = 0;
public static byte [] RecvData(Socket socket, byte[] buffer, int outTime,string forDataOnly)
{
if (socket == null || socket.Connected == false)
{
Log.WriteLog("参数socket 为null,或者未连接到远程计算机");
// throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == 0)
{
Log.WriteLog("参数buffer 为null ,或者长度为 0");
//throw new ArgumentException("参数buffer 为null ,或者长度为 0");
}
#region//接长度并自动调整接收内存byte[]的大小
int btlenInt = BufferAutoLength(socket);
buffer = new byte[btlenInt];

#endregion
buffer.Initialize();
int left = buffer.Length;
int curRcv = 0;
int Rcvlen = 0;
int flag = 0;
int recTimes = 0;
try
{
while (true)
{
//if (socket.Poll(outTime * 1000000, SelectMode.SelectRead))
//{
try
{
// 已经有数据等待接收
curRcv = socket.Receive(buffer, Rcvlen, left, SocketFlags.None);
recTimes++;
left -= curRcv;
Rcvlen += curRcv;
if (left == 0)
{ // 数据已经全部接收
flag = 0;
Ip.TCPtrance.Log.WriteControlText("【√】网络正确接收(flag = 0)" + " " + " 发送结果状态【" + flag.ToString() + "】 ", Form1.richTextBox1);
break;
}
else
{
if (curRcv > 0)
{ // 数据已经部分接收
continue;
}
else
{ // 出现错误

flag = -2;
Ip.TCPtrance.Log.WriteControlText("【×】网络错误接收(flag = -2)" + " " + " 发送结果状态【" + flag.ToString() + "】 ", Form1.richTextBox1);

break;
}
}
}
catch
{
flag = -1;
Ip.TCPtrance.Log.WriteControlText("【×】网络错误接收(flag = -1)" + " " + " 发送结果状态【" + flag.ToString() + "】 ", Form1.richTextBox1);
break;
}
//}
//else
//{ // 超时退出

//}
}
}
catch (SocketException e)
{
Log.WriteLog(e);
flag = -3;
}
//return flag ; ;
temFlg = flag;
Ip.TCPtrance.Log.WriteControlText("【 】网络接收次数 =" + " " + " 【" + recTimes.ToString() + "】 ", Form1.richTextBox1);
return buffer;
}

private static int BufferAutoLength(Socket socket)
{
byte[] btlen = new byte[512];
socket.Receive(btlen);
string btlenStr = Encoding.UTF8.GetString(btlen).Split(new char[] { '|' })[0];
//while (btlenStr == "HBstoped")
//{
// socket.Receive(btlen);
// btlenStr = Encoding.UTF8.GetString(btlen).Split(new char[] { '|' })[0];
//}
int btlenInt = 0;
try { btlenInt = Convert.ToInt32(btlenStr); }
catch { Log.WriteLog("接收长度失败"); }
return btlenInt;
}

#endregion


多谢各位支持。散分。
大光呢 2010-08-07
  • 打赏
  • 举报
回复
我贴出我的 网络传输代码
server端


#region//自动识别长度发送数据
public static int SendData(Socket socket, byte[] buffer, int outTime,string ForSendDataOnly)
{
if (socket == null || socket.Connected == false)
{
Log.WriteLog("参数socket 为null,或者未连接到远程计算机");
// throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == 0)
{
Log.WriteLog("参数buffer 为null ,或者长度为 0");
// throw new ArgumentException("参数buffer 为null ,或者长度为 0");
}

#region//自动识别并发送长度
int len = buffer.Length;
byte[] btLen = Encoding.UTF8.GetBytes(len.ToString()+"|");
byte[] btLenForSend = new byte[512];
btLen.CopyTo(btLenForSend, 0);
socket.Send(btLenForSend);


#endregion
int flag = 0;
try
{
int left = buffer.Length;
int sndLen = 0;

while (true)
{
//if ((socket.Poll(outTime * 1000000, SelectMode.SelectWrite) == true))
//{
try
{
// 收集了足够多的传出数据后开始发送
sndLen = socket.Send(buffer, sndLen, left, SocketFlags.None);
left -= sndLen;
if (left == 0)
{ // 数据已经全部发送
flag = 0;
break;
}
else
{
if (sndLen > 0)
{ // 数据部分已经被发送
continue;
}
else
{ // 发送数据发生错误
flag = -2;
break;
}
}
}
catch
{
flag = -1;
break;
}
//else
//{ // 超时退出
// flag = -1;
// break;
//}
}
}
catch (SocketException e)
{
Log.WriteLog(e);
flag = -3;
}
return flag;
}
#endregion


Client 端 接收数据代码



#region//自动识别长度接收数据
public static int temFlg = 0;
public static byte [] RecvData(Socket socket, byte[] buffer, int outTime,string forDataOnly)
{
if (socket == null || socket.Connected == false)
{
Log.WriteLog("参数socket 为null,或者未连接到远程计算机");
// throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == 0)
{
Log.WriteLog("参数buffer 为null ,或者长度为 0");
//throw new ArgumentException("参数buffer 为null ,或者长度为 0");
}
#region//接长度并自动调整接收内存byte[]的大小
int btlenInt = BufferAutoLength(socket);
buffer = new byte[btlenInt];

#endregion
buffer.Initialize();
int left = buffer.Length;
int curRcv = 0;
int flag = 0;

try
{
while (true)
{
//if (socket.Poll(outTime * 1000000, SelectMode.SelectRead))
//{
try
{
// 已经有数据等待接收
curRcv = socket.Receive(buffer, curRcv, left, SocketFlags.None);
left -= curRcv;
if (left == 0)
{ // 数据已经全部接收
flag = 0;
break;
}
else
{
if (curRcv > 0)
{ // 数据已经部分接收
continue;
}
else
{ // 出现错误
flag = -2;
break;
}
}
}
catch
{
flag = -1;
break;
}
//}
//else
//{ // 超时退出

//}
}
}
catch (SocketException e)
{
Log.WriteLog(e);
flag = -3;
}
//return flag ; ;
temFlg = flag;
return buffer;
}

private static int BufferAutoLength(Socket socket)
{
byte[] btlen = new byte[512];
socket.Receive(btlen);
string btlenStr = Encoding.UTF8.GetString(btlen).Split(new char[] { '|' })[0];
int btlenInt = 0;
try { btlenInt = Convert.ToInt32(btlenStr); }
catch { Log.WriteLog("接收长度失败"); }
return btlenInt;
}
#endregion


原来使用了 if (socket.Poll(outTime * 1000000, SelectMode.SelectRead)),CS两端都用了这个判断,后来改成现在的 try{}catch{}

有什么问题,请提示。
大光呢 2010-08-07
  • 打赏
  • 举报
回复

这个错是偶尔报出的。
索引位置 不定,大概范围是20~150之间,都有可能。[FF]这个值每次都这样提示,每次我跟踪数据看到的都不是[FF],见图中示例为57.
ms的数据是从socket接收过来的。
不是每次都有这个错误,是偶尔报出。如果我加快网络请求(点一次请求server端发一次序列化好的dataset数据),这个错误出现的概率就大很多(也不是每次都报错),还有可能报另一个错误“调用目标发生异常”


难道问题还在网络数据接收吗?
我还没追查网络数据。测试表明,如果是小数据,table 4列 top100 以内,几乎不报任何错误(不管请求速度再快),如果是稍大的数据 table 4列 top8888左右(跨度2000),很容易出现上述错误,哪怕请求的速度很一般(正常速度点击button事件请求)

请教各位朋友,帮我分析一下。
萨拉嘿 2010-08-07
  • 打赏
  • 举报
回复
你多调试几次,注意报错时的一些操作问题,报错时你的接收缓冲区是否被正确赋值,发送端错误操作导致序列化时对象被错误赋值,你再接收后反序列化也能报这个错误。。。仔细看看吧,我也出现过类似的问题
  • 打赏
  • 举报
回复
好乱的代码,lz是写c++的吧?c#程序员不会写这么乱的socket代码吧!
wuyq11 2010-08-05
  • 打赏
  • 举报
回复
反序列化代码问题
MemoryStream ms = new MemoryStream(data);
ms.Position=0
BinaryFormatter formatter = new BinaryFormatter();
obj = formatter.Deserialize(ms);
大光呢 2010-08-05
  • 打赏
  • 举报
回复
UP
大光呢 2010-08-05
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 hdt 的回复:]
客户端,服务器端
序列化的对象版本要保持一致
[/Quote]
我正在考虑这个 要求。
不知道兄台 指的对象版本 作何解释。
我这里目前的情况是 server/client 都是在VS2010(选用.NET2.0环境)环境,处在同一个电脑上(我本机),SQLserver也在我本机(sql2000)(网络server也试验过,报同样问题)。

我还有一个很大的不解:如果真是存在问题,为什么会有时候正确执行(client端正常处理所有过程),有时候又不能执行,报出那个错误呢?
真相重于对错 2010-08-05
  • 打赏
  • 举报
回复
客户端,服务器端
序列化的对象版本要保持一致
加载更多回复(6)

110,587

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧