c# - 将可变长度结构转换为 byte[]

标签 c# serialization data-structures

我正在尝试将网络数据包发送到硬件设备。我想使用一种巧妙的、面向对象的方法,这样我就可以在更高层次上使用它。数据包有几个可变长度的字段。显然字节布局是很有讲究的。

这是一个表示我需要发送的数据包的结构:

[StructLayout(LayoutKind.Sequential)]
public struct Packet
{
   public UInt16 Instruction;
   public UInt16 Length; //length of data field
   public UInt32 SessionHandle;

   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
   public byte[] SenderContext;

   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
   public byte[] MessageData;
}

MessageData[] 可以是任意长度,我将其固定为 8 个字节作为开始。

这是我创建一个 byte[] 以通过 Socket 发送它的尝试:

public static byte[] ToBytes(Packet ep)
{
   Byte[] bytes = new Byte[Marshal.SizeOf(typeof(Packet))];
   GCHandle pinStructure = GCHandle.Alloc(ep, GCHandleType.Pinned);
   try
   {
      Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
      return bytes;
   }
   finally
   {
      pinStructure.Free();
   }
}

但我收到:

ArgumentException : Object contains non-primitive or non-blittable data.

我认为在结构中设置 SizeConst 会解决这个问题?无论如何,我比这更迷茫,因为硬件设备需要一个可变长度的数据包,我想利用它。

我可以手动将数据包逐字节放在一起,一切都很好。但我知道必须有更好的方法,而且我一定是走错了路。

有什么想法吗?

最佳答案

CLR 不允许您使用具有与引用类型重叠的字段的结构。你的情况下的两个数组。它与垃圾收集器非常不兼容,它无法跟踪对象引用。并且会非常不安全,因为它允许后门进入堆,直接操纵对象引用的值。

在您的特定情况下这样做没有意义,因为两个数组重叠并且大小完全相同。一个人就能很好地完成工作。

关于c# - 将可变长度结构转换为 byte[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3736589/

相关文章:

java - simpleframework,将空元素反序列化为空字符串而不是 null

c++ - 键值映射中的部分查找,其中键本身是键值映射

c# - 如何按名称从excel中的特定工作表中读取

c# - 无法加载文件或程序集 "Newtonsoft.Json.Net"(HRESULT : 0x80131040) 异常

c# - Protobuf-net 编译为 DLL 字符串 [] 导致损坏的 dll

c# - 我可以序列化 C# Type 对象吗?

c++ - 在编译时创建大型 HashMap 的最佳方法(C++)?

java - 是否有可能实现类似于 subList(a,b) 的方法,但当 a>b 时该方法有效?

c# - 处理 JSON 单个对象和数组

c# - Html.dropdownlist 不显示下拉字段中的默认/选定值