C# 与linux的结构体通讯
很久没写博客了,有时就是坚持不了,现在重新下决定,用博客记录自己的所学,巩固巩固。
公司项目曾涉及与linux系统通讯的程序,参考了些例子实现了,现在写下了,做个记录供以后查阅,废话不说了,现在开始......
首先定义C#里的结构体:
using System.Runtime.InteropServices;
[Serializable] // 指示可序列化
[StructLayout(LayoutKind.Sequential, Pack = 1)] // 按1字节对齐
public struct MyStruct
{
public int id;
// 声明一个字符数组,大小为20
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
private char[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
private char[] password;
public string Name
{
get{ new String(this.name).Trim('\0');}
set{ this.name = value.PadRight(20, '\0').ToCharArray();}
}
public string Password
{
get{ new String(this.password).Trim('\0');}
set{ this.password= value.PadRight(16, '\0').ToCharArray();}
}
}
注意 set{ this.name = value.PadRight(20, '\0').ToCharArray();}这行代码,value的长度不足20(上面声明的大小:[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] ),要在其后补'\0'.
接下来,是重点就是将上面的结构体转换成Linux系统可识别的Byte数组:
using System.Runtime.InteropServices;
/// <summary>
/// 将结构转换为字节数组
/// </summary>
/// <param name="obj">结构对象</param>
/// <returns>字节数组</returns>
public byte[] StructToBytes(object obj)
{
//得到结构体的大小
int size = Marshal.SizeOf(obj);
//创建byte数组
byte[] bytes = new byte[size];
//分配结构体大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将结构体拷到分配好的内存空间
Marshal.StructureToPtr(obj, structPtr, false);
//从内存空间拷到byte数组
Marshal.Copy(structPtr, bytes, 0, size);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回byte数组
return bytes;
}
/// <summary>
/// byte数组转结构
/// </summary>
/// <param name="bytes">byte数组</param>
/// <param name="type">结构类型</param>
/// <returns>转换后的结构</returns>
public object BytesToStruct(byte[] bytes, Type type)
{
//得到结构的大小
int size = Marshal.SizeOf(type);
//byte数组长度小于结构的大小
if (size > bytes.Length)
{
//返回空
return null;
}
//分配结构大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构
object obj = Marshal.PtrToStructure(structPtr, type);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回结构
return obj;
}
现在就看看如何将结构体发生给Linux端:
MyStruct mystruct=New MyStruct(); mystruct.id=1; mystruct.Name="karl"; mystruct.Password="123456"; byte[] senddata=StructToBytes(mystruct); TcpClient client= new TcpClient((ip,port); ); NetworkStream ns = client.GetStream(); ns.Write(senddata,0,senddata.Length); // 发送 ns.flush(); client.close();
Linux端也要定义一个对应的结构体:
typedef struct myStruct
{
int id;
char name[20];
char password[16];
} myStructType;
接下来linux端怎么接收byte数组转换出结构就不讲了,因为本人只写过一年的单片机程序,也不熟悉Linux端C代码如何写了。貌似有一点要注意的是定义的结构体的大小(字节的总数)最好是8的倍数,好像linux端有字节对齐的问题,曾试过定义的结构不为8的倍数时,linux端的结构大小和实际的不一致。
到此结束了,本人文笔水平有限,写得有什么不足的,乐意接受大家的建议批评。
作者:碎心炼心
出处:http://www.cnblogs.com/karl-F
本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号