小弟最近在研究利用Marshal实现序列化和反系列化,主要是使用Marshal类里的两个方法,StructureToPtr和PtrToStructure,这两个类的具体讲解和用法我就不多赘述 了,具体见[url=http://blog.csdn.net/wem520/article/details/9101549][/url],下面说我碰到的问题,我的需求是对一个类的对象通过StructureToPtr序列化成byte[]数组,然后通过TCP Socket传输到另外一个解决方案,再用PtrToStructure反序列化出来这个对象。现在的问题是类的字段类型问题,就是我一个属性是string类型,其余的都是int类型。测试结果发现如果在同一个API里,这个方法能完美实现,但是经过传输再反序列化后int类型可以反序列化出来而string字段就为空或者乱码。小弟百思不得其解,特来求高手帮忙分析解疑。具体代码如下:
API直接序列化反序列化
[code=csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.name = "joseph";
p.age = 18;
p.high = 188;
p.kg = 143;
p.tel = 15689;
byte[] bs = StructToBytes(p);
Person2 py2 = (Person2)BytesToStruct(bs, typeof(Person2));
Console.ReadKey();
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class Person
{
public string name { get; set; }
public int age { get; set; }
public int high { get; set; }
public int kg { get; set; }
public int tel { get; set; }
}
//1、struct转换为Byte[]
public static Byte[] StructToBytes(Object structure)
{
Int32 size = Marshal.SizeOf(structure);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(structure, buffer, false);
Byte[] bytes = new Byte[size];
Marshal.Copy(buffer, bytes, 0, size);
return bytes;
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
//2、Byte[]转换为struct
public static Object BytesToStruct(Byte[] bytes, Type strcutType)
{
Int32 size = Marshal.SizeOf(strcutType);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, strcutType);
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
}
}
[/code]
这个方案输出结果完全正确!
下面是我的传输Demon
序列化公共类
[code=csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
namespace Serialization
{
public class Serializable
{
public static Byte[] StructToBytes(Object structure)
{
Int32 size = Marshal.SizeOf(structure);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(structure, buffer, true);
Byte[] bytes = new Byte[size];
Marshal.Copy(buffer, bytes, 0, size);
return bytes;
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
//2、Byte[]转换为struct
public static Object BytesToStruct(Byte[] bytes, Type strcutType)
{
Int32 size = Marshal.SizeOf(strcutType);
IntPtr buffer = Marshal.AllocHGlobal(size);
try
{
Marshal.Copy(bytes, 0, buffer, size);
return Marshal.PtrToStructure(buffer, strcutType);
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
public class Person
{
public string name { get; set; }
public int age { get; set; }
public int high { get; set; }
public int kg { get; set; }
public int tel { get; set; }
}
}
}
[/code]
下面是调用,分为客户端和服务器,客户端将内容通过Socket传输给服务器(可以看到我中见的一些注释是在尝试编码格式来解决string类型出错)
Client
[code=csharp]
byte[] Data;
Channel channel;
Serializable.Person p;
private void send_Click(object sender, EventArgs e)
{
p = new Serializable.Person();
//byte[] byt = System.Text.UnicodeEncoding.UTF8.GetBytes(name.Text.ToString());
//p.name = System.Text.UnicodeEncoding.UTF8.GetString(byt);
p.name = name.Text.ToString();
p.age = int.Parse(age.Text);
p.high = int.Parse(high.Text);
p.kg = int.Parse(kg.Text);
p.tel = int.Parse(tel.Text);
Data = Serializable.StructToBytes(p);
if (channel != null && Data != null)
{
channel.Send(Data);
Log("发送成功");
}
else
{
Log("数据体为空或信道连接失败");
return;
}
}
[/code]
Server(我只贴出接受数据的方法)
[code=csharp]
public void DataReceive(object sender, ChannelReceiveArg arg)
{
Log("接收到数据" + arg.Data.ToString());
Serializable.Person p = (Serializable.Person)Serializable.BytesToStruct(arg.Data, typeof(Serializable.Person));
name.Text = p.name;
age.Text = p.age.ToString();
high.Text = p.high.ToString();
kg.Text = p.kg.ToString();
tel.Text = p.tel.ToString();
}
[/code]
这个是我的测试,和API思路一样,只是中间多虑步传输,但就是会有各种问题,有时候会在 return Marshal.PtrToStructure(buffer, strcutType);处报这样的错[img=http://img.bbs.csdn.net/upload/201404/01/1396336717_779070.png][/img],有时候运行正常,但是就是那个name出不来。我真是快疯了,求大神啊!
博主在尝试使用Marshal进行序列化和反序列化时遇到问题,具体表现为:通过StructureToPtr和PtrToStructure方法处理的包含字符串和整型的类对象,在经过TCP Socket传输后,整型字段能够正确反序列化,而字符串字段出现为空或乱码的情况。代码示例中展示了直接序列化和反序列化成功的API实现,以及出现问题的传输过程。问题可能出在编码格式不一致或字符串处理上。
756

被折叠的 条评论
为什么被折叠?



