ravi
ravi

Reputation: 6338

Custom UDP Packet structure in C#

I wanted to send a UDP packet, which has following structure

  1. Packet size is 8 bytes
  2. Header field of uint16 data type
  3. Command field of uint16 data type
  4. Number field of uint32 data type

I designed the packet in following manner:

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);

Does a better way exist to do the same as above?

Upvotes: 0

Views: 1513

Answers (2)

Trillian
Trillian

Reputation: 6447

You could also use .NET's built-in marshaling features or unsafe code:

[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; }

Both of those solutions will encode your fields with the local machine endianness, however. This might or might not be a problem for you.

Upvotes: 2

Lee
Lee

Reputation: 144206

You could use BitConverter e.g.:

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

Upvotes: 3

Related Questions