首页 > 解决方案 > 在 C# 上构建二进制数据包

问题描述

我正在尝试构建一个结构如下的数据包:

标题操作

其中 HEADER 大小为 4 个字节,包含总数据包长度。OP 大小为 2 个字节,包含一个整数。

例如,我正在尝试作为 OP“3”发送。所以数据包应该变成 {2, 0, 0, 0, 3, 0} 其中 2, 0, 0, 0 是标头,3, 0 是 OP(填充到左侧)

标签: c#binarypacket

解决方案


您将需要以下两种方法来执行与字节数组的转换。我假设这都是Little Endian。

/// <summary>
/// Converts the supplied object to a byte array.
/// </summary>
public static byte[] ToByteArray(object obj)
{
    int len = Marshal.SizeOf(obj);
    byte[] arr = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    Marshal.StructureToPtr(obj, ptr, true);
    Marshal.Copy(ptr, arr, 0, len);
    Marshal.FreeHGlobal(ptr);
    return arr;
}

/// <summary>
/// Maps the supplied byte array onto a structure of the specified type.
/// </summary>
public static T ToStructure<T>(byte[] byteArray)
{
    GCHandle h = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
    T result = (T)Marshal.PtrToStructure(h.AddrOfPinnedObject(), typeof(T));
    h.Free();
    return result;
}

现在您只需要一个保存数据的结构。它看起来像这样:

[StructLayout(LayoutKind.Explicit)]
public struct PacketHeader
{
    public UInt32 HEADER;
    public UInt16 OP;
}

然后你所要做的就是PacketHeader用数据填充一个实例,并将其转换为一个字节数组,如下所示:

var packetHeader = new PacketHeader
{
    HEADER=2,
    OP=3
};

var bytes = ToByteArray(packetHeader);

要反转该过程:

var packetHeader p FromByteArray<PacketHeader>(bytes);

推荐阅读