C# 结构体与byte[]之间的转换,以及C#与C/C++服务器之间的通信

说起结构体与byte[]之间的转换,主要是为了能够让结构体通过socket进行传输,实现通信。 首先我们来看看C下面的一个结构体:

1
2
3
4
5
6
7
#prgrma pack(1)
struct pack
{
    uint8_t type;
    uint32_t lenght;
}
#prgrma pack()

这里我们需要字节对齐,以保证两个平台之间数据传输的正确性。

1
2
3
4
5
6
7
[Serializable]
[StructLayout(LayoutKind.Sequential,Pack=1)]
public struct pack
{
    byte type;
    int lenght;
}

下面上一张表,以表示在C#下面的数据类型与C/C++的不同:

QQ截图20151208161309.png

如果我们是在C/C++下面使用send/recv接收数据的话,直接将指针传递给函数就可以了,但是在c#下面显然行不通,c#的socket.send方法与socket.recive方法都只能接受或者发送byte[]类型,如果我们需要发送结构体,就需要将结构体转换为byte[]类型或者将字节数组转换为我们需要的结构体。 我们可以编写两个函数来实现两种不同类型的转换,在编写的时候我们需要:

1
using System.Runtime.InteropServices;

下面我们就来写这两个函数,StructToBytes和BytesToStruct:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public 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);
    //Marshal.FreeHGlobal(structPtr);
    return bytes;
}

public object BytesToStruct(byte[] bytes,Type type)
{
    int size = Marshal.SizeOf(type);
    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;
}
Built with Hugo
主题 StackJimmy 设计