如何从socket接收字节数组,到C#结构

我必须开发一个服务(C#),它通过TCP Socket从网络设备读取数据并转换它是C#结构。

我基于现有的旧Delphi应用程序,它正在做所有这些事情,我必须在C#中迁移逻辑。

编辑:我从原始数据结构的C-Source获得了一个快照:

struct _RequestMsgStruct { UCHAR request_ver; //In DELPHI it is represented as Byte USHORT mac_addr[3]; /* MAC Address */ UINT product_type; //In DELPHI - Cardinal UCHAR supply_type; //In DELPHI - Byte short reserved0; //In DELPHI - SmallInt UCHAR oper_ver[4]; //In DELPHI - CARDINAL !!! USHORT brd_id; //In DELPHI - WORD unsigned short exp_id1; //In DELPHI - WORD //In DELPHI - string[15]; //Array [0..15] of char; UCHAR serial_no[16]; /* Serial Number. 16th char have to be NULL */ UCHAR _name[32]; /* Name */ //Length of payload may vary //In DELPHI - string[31] float data_avg; //In DELPHI - Single ULONG key[5]; //In DELPHI - array [0..19] of Byte }__attribute__ ((packed)); 

Delphi Packed记录包含200多个不同类型的字段……看起来大致如下:

  TREC_DATA = packed record ID : Byte; MAC_ADDRESS : array [0..5] of Byte; fieldCard : cardinal; fieldSI : SmallInt; fieldW : WORD; SERIAL_NUMBER : string[15]; //Array [0..15] of char; fieldSingle : Single; fieldArrOfB : array [0..19] of Byte; end; 

要在Delphi中将字节数组移动到结构,有下一个代码:

 Move(inBytesArr[StartIdx], DelphiStruct, aMsgSize) 

要转换字符串文件(例如SERIAL_NUMBER),还有这样的代码:

 var pc: Pchar; ... pc := @inBytesArr[StartIdx + SerialN_Pos_Idx]; DelphiStruct.SERIAL_NUMBER := pc; 

我第一次处理这种转换,我不知道从哪里开始:

  • 如何将此结构转换为c#? – 我应该使用LayoutKind.SequentialLayoutKind.Explicit ,还是wiyhout [FieldOffset(N)]属性? – 我如何在目标c#结构中声明字节数组:作为fixed缓冲区或使用[MarshalAs(UnmanagedType.ByValArray...)]属性?

  • 哪种方法可以将输入字节数组编组到最终的C#结构:使用Marshal.PtrToStructure或GCHandle.Alloc(bytes,GCHandleType.Pinned)+ AddrOfPinnedObject

请帮助我,至少,从我需要开始的地方获得低调的起点。

默认情况下,Delphi的打包记录按单字节边界对齐字段。
因此,你应该使用这样的东西:

 [StructLayout(LayoutKind.Sequential, Pack = 1)] struct TREC_DATA { public byte ID; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] MAC_ADDRESS; public uint fieldCard; public short fieldSI; public ushort fieldW; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] SERIAL_NUMBER; public float fieldSingle; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] fieldArrOfB; } 

唯一我不确定(现在没有Deplhi就无法测试)的是SERIAL_NUMBER字段。

更新后:原来,SERIAL_NUMBER只是一个以空字符结尾的字符串。