Reputation: 6338
I wanted to send a UDP packet, which has following structure
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
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
Reputation: 144206
You could use BitConverter
e.g.:
var headerBytes = BitConverter.GetBytes(header);
Array.Copy(headerBytes, 0, requestPacket, 0, 2);
Upvotes: 3