C#中的自定义UDP数据包结构

时间:2014-03-28 17:35:59

标签: c# sockets

我想发送一个UDP数据包,其结构如下

  1. 数据包大小为8个字节
  2. uint16数据类型的标题字段
  3. uint16数据类型的命令字段
  4. uint32数据类型的数字字段
  5. 我按照以下方式设计了数据包:

    ushort header = (ushort)IPAddress.HostToNetworkOrder(0x0001);
    ushort command = (ushort)IPAddress.HostToNetworkOrder(10);
    uint number = (uint)IPAddress.HostToNetworkOrder(2);
    
    byte[] requestPacket = new byte[8];
    requestPacket[0] = (byte)(header >> 8 & 0xFF);
    requestPacket[1] = (byte)(header & 0xFF);
    requestPacket[2] = (byte)(command >> 8 & 0xFF);
    requestPacket[3] = (byte)(command & 0xFF);
    requestPacket[4] = (byte)(number >> 24 & 0xFF);
    requestPacket[5] = (byte)(number >> 16 & 0xFF);
    requestPacket[6] = (byte)(number >> 8 & 0xFF);
    requestPacket[7] = (byte)(number & 0xFF);
    

    是否有更好的方法与上述相同?

2 个答案:

答案 0 :(得分:3)

您可以使用BitConverter例如:

var headerBytes = BitConverter.GetBytes(header);
Array.Copy(headerBytes, 0, requestPacket, 0, 2);

答案 1 :(得分:2)

您还可以使用.NET的内置编组功能或不安全的代码:

[StructLayout(LayoutKind.Sequential, Pack = 1)] // Ensure tight packing
public struct Packet
{
    public ushort Header;
    public ushort Command;
    public uint Number;
}

Packet packet = new Packet { ... };
byte[] packetData = new byte[Marshal.Sizeof<Packet>()];

// Using marshaling
var handle = default(GCHandle);
try
{
    handle = GCHandle.Alloc(packetData, GCHandleType.Pinned);
    Marshal.StructureToPtr(packet, handle.AddrOfPinnedObject(), fDeleteOld: false);
}
finally
{
    if (handle.IsAllocated) handle.Free();
}

// Using unsafe code (careful, assumes marshaled size == size in memory!)
unsafe { fixed(byte* packedPtr = packetData) *(Packet*)packedPtr = packet; }

但是,这两种解决方案都会使用本地计算机字节序编码您的字段。这对您来说可能是也可能不是问题。