小弟近来使用C#中的TCPClient和NetStream传输类对象。在传输的时候使用到了序列化和反序列化。问题是这样。经测试,小弟在本地可以完成序列化和反序列化,不过传输到其他计算机之后就不能完成反序列化。代码是这样的。求救啊!//序列化类对象
static public byte[] Serialize(object obj)
{
BinaryFormatter binaryF = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
binaryF.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[(int)ms.Length];
ms.Read(buffer, 0, buffer.Length);
ms.Close();
return buffer;
}
//反序列化类对象
static public object Deserialize(byte[] buffer)
{
BinaryFormatter binaryF = new BinaryFormatter();
MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length, false);
object pag = binaryF.Deserialize(ms);
ms.Close();
return pag;
}//客户端向服务器发送连接请求
TcpClient client = connectToServer();
NetworkStream clientstream = client.GetStream();
Package pag = new Package();
pag.flag = 1;
pag.player_name = txt_name.Text;
buffer = Serialize((object)pag);
Package p = new Package();
p = Deserialize(buffer) as Package;
for (j = 0; j < buffer.Length; j++)
{
requestbuffer[j] = buffer[j];
}
requestbuffer[j] = (byte)'#';
clientstream.Write(requestbuffer, 0, requestbuffer.Length);//服务端接收数据
byte[] requestbuffer = new byte[bufferSize];
byte[] responsebuffer = new byte[bufferSize];
int readBytes = 0;
int i;
readBytes = clientstream.Read(requestbuffer, 0, bufferSize);
for (i = 0; i < requestbuffer.Length; i++) {
if (requestbuffer[i] == '#') {
break;
}
}
byte[] buffer = new byte[i];
for (int j = 0; j < buffer.Length; j++) {
buffer[j] = requestbuffer[j];
}
Package clientpackage = new Package();
clientpackage = Deserialize(buffer) as Package;
代码执行到clientpackage = Deserialize(buffer) as Package;时,在反序列化函数中的
object pag = binaryF.Deserialize(ms);报错----输入流是无效的二进制格式。开始内容(以字节为单位)是: 01-00-00-00-06-03-00-00-00-06-77-61-6E-67-6C-66-09...可是在本地机上也是这个二进制串,能够反序列化啊?求救是怎么回事?在线等啊!
static public byte[] Serialize(object obj)
{
BinaryFormatter binaryF = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
binaryF.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[(int)ms.Length];
ms.Read(buffer, 0, buffer.Length);
ms.Close();
return buffer;
}
//反序列化类对象
static public object Deserialize(byte[] buffer)
{
BinaryFormatter binaryF = new BinaryFormatter();
MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length, false);
object pag = binaryF.Deserialize(ms);
ms.Close();
return pag;
}//客户端向服务器发送连接请求
TcpClient client = connectToServer();
NetworkStream clientstream = client.GetStream();
Package pag = new Package();
pag.flag = 1;
pag.player_name = txt_name.Text;
buffer = Serialize((object)pag);
Package p = new Package();
p = Deserialize(buffer) as Package;
for (j = 0; j < buffer.Length; j++)
{
requestbuffer[j] = buffer[j];
}
requestbuffer[j] = (byte)'#';
clientstream.Write(requestbuffer, 0, requestbuffer.Length);//服务端接收数据
byte[] requestbuffer = new byte[bufferSize];
byte[] responsebuffer = new byte[bufferSize];
int readBytes = 0;
int i;
readBytes = clientstream.Read(requestbuffer, 0, bufferSize);
for (i = 0; i < requestbuffer.Length; i++) {
if (requestbuffer[i] == '#') {
break;
}
}
byte[] buffer = new byte[i];
for (int j = 0; j < buffer.Length; j++) {
buffer[j] = requestbuffer[j];
}
Package clientpackage = new Package();
clientpackage = Deserialize(buffer) as Package;
代码执行到clientpackage = Deserialize(buffer) as Package;时,在反序列化函数中的
object pag = binaryF.Deserialize(ms);报错----输入流是无效的二进制格式。开始内容(以字节为单位)是: 01-00-00-00-06-03-00-00-00-06-77-61-6E-67-6C-66-09...可是在本地机上也是这个二进制串,能够反序列化啊?求救是怎么回事?在线等啊!
static public byte[] Serialize(object obj)
{
BinaryFormatter binaryF = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
binaryF.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[(int)ms.Length];
ms.Read(buffer, 0, buffer.Length);
ms.Close();
return buffer;
}
//反序列化类对象
static public object Deserialize(byte[] buffer)
{
binaryF = new BinaryFormatter();
MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length, false);
object pag = binaryF.Deserialize(ms);
ms.Close();
return pag;
}
谁能给个解决方法啊?最好能指点下代码的!拜托啊!
我就是这样做的,下面部分单独出来生成dll,两边都引用,代码如下using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Xml.Serialization;
using System.IO.Compression;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace CommonClassLib
{
[Serializable()]
public class ChangeRecord
{
/// <summary>
/// 主键
/// </summary>
public string Guid { get; set; }
/// <summary>
/// 表名
/// </summary>
public string TableName { get; set; }
/// <summary>
/// 表中主键名
/// </summary>
public string PKFieldName { get; set; }
/// <summary>
/// 同步记录id
/// </summary>
public string SyncronId { get; set; }
/// <summary>
/// 操作类型:1增2删3改
/// </summary>
public string Operate { get; set; }
/// <summary>
/// 记录处理状态
/// </summary>
public string State { get; set; }
/// <summary>
/// 变化触发时间
/// </summary>
public DateTime TriggTime { get; set; }
} [Serializable]
public class MyList<T> : List<T>
{ } [Serializable]
public class KVPair
{
public string Field { get; set; }
public string Value { get; set; }
} /// <summary>
/// 二进制序列化
/// </summary>
public class SerializableObj<T> where T : IEnumerable
{
public static Byte[] Serialize(T obj)
{
try
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, obj);
ms.Position = 0;
byte[] buffers = ms.ToArray();
ms.Close();
ms.Dispose();
return Compress(buffers);
}
catch (Exception ex)
{
throw ex;
}
} public static byte[] Compress(byte[] buffer)
{
MemoryStream ms = new MemoryStream();
GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true);
//byte[] returnBuffer=new byte [];
gzip.Write(buffer, 0, buffer.Length);
gzip.Close();
ms.Position = 0;
byte[] rebuffer = new byte[ms.Length];
ms.Read(rebuffer, 0, int.Parse(ms.Length.ToString()));
return rebuffer;
}
} /// <summary>
/// 二进制反序列化
/// </summary>
public class Deserizlize<T> where T : class, IEnumerable
{
public Deserizlize()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public static byte[] Decompress(byte[] buffer)
{
try
{
MemoryStream ms = new MemoryStream(buffer);
ms.Position = 0;
GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress);
byte[] rebuffer = new byte[100];
MemoryStream msre = new MemoryStream();
int readcont = gzip.Read(rebuffer, 0, rebuffer.Length);
while (readcont > 0)
{
msre.Write(rebuffer, 0, readcont);
readcont = gzip.Read(rebuffer, 0, rebuffer.Length);
}
return msre.ToArray();
}
catch (Exception ex)
{ throw ex;
}
} public static T Deserilize(byte[] buffer)
{
try
{
byte[] debuffer = Decompress(buffer);
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(debuffer);
ms.Position = 0;
T obj = bf.Deserialize(ms) as T;
return obj;
}
catch (Exception ex)
{ throw ex;
}
}
}
}
BinaryFormatter brFormatter = new BinaryFormatter();
//二进制序列化的时候,有个借口,下面的
brFormatter.Binder = new ConvertAssemblyBinder();/// <summary>
/// 控制将序列化对象绑定到类型的过程
/// </summary>
public sealed class ConvertAssemblyBinder : SerializationBinder
{
/// <summary>
/// 控制二进制序列化类型转换
/// </summary>
/// <param name="assemblyName"></param>
/// <param name="typeName"></param>
/// <returns></returns>
// 在序列化过程中,格式化程序传输创建正确类型和版本的对象的实例所需的信息。
// 此信息通常包括对象的完整类型名称和程序集名称。
// 程序集名称包含程序集的名称、版本和强名称(请参见具有强名称的程序集)散列。
// 默认情况下,反序列化将使用此信息创建等同对象的实例(安全策略所限制的任何程序集加载属于例外)。
// 因为类已经在程序集之间移动或者因为在服务器和客户端上要求类的不同版本,有些用户需要控制要加载哪些类。
// 这是一个抽象基类。所有联编程序都扩展此类。
// 给继承者的说明 从 SerializationBinder 继承时,必须重写以下成员:BindToType。 // 由于服务器和客户端共同使用同一个类型,进行数据传递,但是服务器和客户端的同一类型处于不同的
// 程序集,需要在反序列化的时候,提供强制类型转换
public override Type BindToType(string assemblyName, string typeName)
{
// 取得当前的程序集名称,取得传递过来,类型名称不修改,都是"TestPro.CSFTcpMsg"
string strCurAssembly = Assembly.GetExecutingAssembly().FullName; // 返回当前对应的类型
Type CurType = Type.GetType(String.Format("{0}, {1}", typeName, strCurAssembly));
return CurType;
}
}
其实就是新建一个class Library的项目,把公共的东西放在里边,在其他项目中添加对此项目的引用罢了
照抄。。只要让BindToType()方法返回你现在的程序集+命名空间序列化类名就可以了。我服务器有个消息类:CSFTcpMsg,但是命名空间是:TcpTestPro.CSFTcpMsg
客户端有个消息类:CSFTcpMsg,但是命名空间是:TestPro.CSFTcpMsg
CSFTcpMsg类定义在服务器端和客户端都是一致的,但是不属于同一命名空间,也不是同一程序集
客户端收到后,反序列化一定会检测程序集信息,不是就报错了
唯一的优点就是体积小,如果楼主采用文本序列化就不存在这样的问题了
这个给你:
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;序列化的方式,6楼的方法已经很标准了
我的代码:我以前也用文本序列化的/// <summary>
/// 反序列化TcpMessage对象
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
// 采用二进制序列化取代了XML序列化,二进制体积小,速度快,但是有一定的限定条件
public static TcpMsg GetMessage_(byte[] Msg)
{
try
{
using (MemoryStream memStream = new MemoryStream(Msg))
{
BinaryFormatter brFormatter = new BinaryFormatter();
brFormatter.Binder = new ConvertAssemblyBinder();
TcpMsg tm = (TcpMsg)brFormatter.Deserialize(memStream); //XmlSerializer xs = new XmlSerializer(typeof(TcpMsg));
//TcpMsg tm = xs.Deserialize(memStream) as TcpMsg;
return tm;
}
}
catch (Exception)
{
return null;
}
}
http://topic.csdn.net/u/20100428/21/d36073ab-5731-4259-bb37-876ae154ad45.html结贴散分!谢谢你们的热心帮助!感激不尽!!