[导读]最近在用C#做一个项目的时候,Socket发送消息的时候遇到了服务端需要接收C++结构体的二进制数据流,这个时候就需要用C#仿照C++的结构体做出一个结构来,然后将其转换成二进制流进行发送,之后将响应消息的二进制数据流转换成C#结构。
最近在用C#做一个项目的时候,Socket发送消息的时候遇到了服务端需要接收C++结构体的二进制数据流,这个时候就需要用C#仿照C++的结构体做出一个结构来,然后将其转换成二进制流进行发送,之后将响应消息的二进制数据流转换成C#结构。
1、仿照C++结构体写出C#的结构来
using System.Runtime.InteropServices;
[Serializable] // 指示可序列化
[StructLayout(LayoutKind.Sequential, Pack = 1)] // 按1字节对齐
public struct Operator
{
public ushort id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] // 声明一个字符数组,大小为11
public char[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public char[] pass;
public Operator(string user, string pass) // 初始化
{
this.id = 10000;
this.name = user.PadRight(11, ''\0'').ToCharArray();
this.pass = pass.PadRight(9, ''\0'').ToCharArray();
}
}
2、注意C#与C++数据类型的对应关系
C++与C#的数据类型对应关系表
API数据类型类型描述C#类型API数据类型类型描述C#类型
WORD16位无符号整数ushortCHAR字符char
LONG32位无符号整数intDWORDLONG64位长整数long
DWORD32位无符号整数uintHDC设备描述表句柄int
HANDLE句柄,32位整数intHGDIOBJGDI对象句柄int
UINT32位无符号整数uintHINSTANCE实例句柄int
BOOL32位布尔型整数boolHWM窗口句柄int
LPSTR指向字符的32位指针stringHPARAM32位消息参数int
LPCSTR指向常字符的32位指针StringLPARAM32位消息参数int
BYTE字节byteWPARAM32位消息参数int
整个结构的字节数是22bytes。
对应的C++结构体是:
typedef struct
{
WORD id;
CHAR name[11];
CHAR password[9];
}Operator;
3、发送的时候先要把结构转换成字节数组
using System.Runtime.InteropServices;
///
/// 将结构转换为字节数组
///
/// 结构对象
/// 字节数组
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;