C# 含动态数组的结构体封送问题本帖最后由 xillscar 于 2012-06-01 13:43:00 编辑求助 C# 含动态数组的结
C# 含动态数组的结构体封送问题
本帖最后由 xillscar 于 2012-06-01 13:43:00 编辑 求助 C# 含动态数组的结构体封送问题:
结构体代码
//结构体代码
public struct DateSkillList
{
public byte datatypes;
public int player_id;
public ArrayList skill_list;
}
//skill_list包含的是一个Skillslistdate的结构体;
public struct Skillslistdate
{
public int skill_id;
public int skill_level;
}
//处理部分
public class bytes
{
public gobyte()
{
DateSkillList msg=new DateSkillList();
Skillslistdate smg=new Skillslistdate();
smg.skill_id=10001;
smg.skill_level=1;
msg.skill_list.add(smg);
byte[] buffer=Tool.StructToBytes(msg);
}
}
//Tool 部分
public class Tool
{
public static byte[] StructToBytes(object obj)
{
int size = Marshal.SizeOf(obj);
byte[] bytes = new byte[size];
IntPtr structPtr = Marshal.AllocHGlobal(size); //分配结构体大小的内存空间
Marshal.StructureToPtr(obj, structPtr, false); //将结构体拷到分配好的内存空间
Marshal.Copy(structPtr, bytes, 0, size); //从内存空间拷到byte数组
Marshal.FreeHGlobal(structPtr); //释放内存空间
return bytes;
}
//网络发送部分
NetWorks.AsyncSendMessage(buffers, clns);
在发送到tool转换的时候出错.求各位大神帮助
[最优解释]StructToBytes 方法
public static byte[] StructToBytes(object obj)
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream())
{
bf.Serialize(stream, obj);
return stream.ToArray();
}
}
[其他解释]是不是因为 结构体中不能用ArrayList 这样的动态数组?
如果是.那么我不可能去一条数据就封送一次吧?
这样得多浪费啊?
有没有其他的办法 可以把从数据库取出来的数据 全部按照一定的格式写入到结构体中进行统一封送?
------其他解决方案--------------------
把 ArrayList 放在结构体了肯定有问题的,关键是读取这封送过去的数据的地方是怎样定义结构体的?
[其他解释]接收的地方 结构体的格式和发送方的结构体格式完全一致
[其他解释]你这里只能用序列化的方式获得byte[],因为你的DateSkillList大小未知,里面含有ArrayList这样的不确定大小的数组。
[其他解释]补充一句 所有的结构体定义的时候都加了
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode), Serializable]
[其他解释]接收程序是什么语言?也是C#?
[其他解释]对的 服务端和客户端都是C#
[其他解释]补充一句 在封送到Tool的时候 异常提示为 无法计算有意义的大小或偏移量
[其他解释]反过来
public static object BytesToStruct(byte[] array)
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream(array))
{
return bf.Deserialize(stream);
}
}
[其他解释]用 BinaryFormatter 这个的话 我客户端的解析就不对了
[其他解释]取带有 ArrayList 时的结构体的长度是没有意义的,ArrayList 是引用类型,存放时就是个指针,大小就 4 字节,里面的内容不会算长度的
[其他解释]那两个结构体,提取出来,放在独立项目中,编译成 dll ,client 和 server 各放一份,引用这个 dll ,读取就没问题了
[其他解释]你是说我单独的吧 DateSkillList 和 Skillslistdate 编译成dll 做引用?
就不用去修改tool的方法吗?
[其他解释]请参考WCF的序列化方式,可以做到两处各自定义的。
[其他解释]感谢大家帮助.我去测试一下
[其他解释]是编译成dll 做引用,tool 里方法参照 8楼 和 10楼 的。
[其他解释]楼主的错误是在int size = Marshal.SizeOf(obj);的时候报错,其实也不是完全没辙,可以修改(重新设计)那个方法,让其识别结构体中的数组长度,然后对其进行填充,至于长度,用[MarshalAs(UnmanagedType.ByValArray, SizeConst = XXX)]标识即可。
[其他解释]我粗略看了下,wcf 是 xml 方式的序列化?
[其他解释]做成 dll 有个好处,修改结构时只要动一处代码
[其他解释]问题已经解决。感谢大家的帮助
[其他解释]在发送的封装的结构体中我定义了一个 byte abyte=0x16 这样的协议编号.
用次方法之后 原来定义的byte类型的协议编号会变成另外的数据.客户端无法正确解析对应的协议