1

I'm trying to build a packet structured as:

HEADER OP

Where HEADER size is 4 bytes, and contains total packet length. OP size is 2 bytes, and contains an integer.

For example, i'm trying to send as OP "3". So packet should become {2, 0, 0, 0, 3, 0} Where 2, 0, 0, 0 is header and 3, 0 is OP (padded to the left)

9
  • OK. What is your specific question about that? Commented Dec 12, 2019 at 23:14
  • I'm sorry. I'm trying to build it using C# but i have no idea on how to convert data to bytes and above all padding data Commented Dec 12, 2019 at 23:17
  • Your first step is to start with a detailed specification of the packet structure. Do you have that? Commented Dec 12, 2019 at 23:18
  • Well all i know, as written above, is that packets are structured before with an header (4 bytes), OP (2 bytes), and if necessary by packet type possible data. In my case i only need to send HEADER + OP, trying to send via Stream.Write the packet i wrote above ({2, 0, 0, 0, 3, 0}) it works, so i need to build this packet only using the OP, so the code will have to understand total packet length (in this case, 2 since OP is 2 bytes) and build the header Commented Dec 12, 2019 at 23:23
  • I'll see if I can cobble together an example below. Commented Dec 12, 2019 at 23:27

1 Answer 1

1

You'll need the following two methods to perform conversions to and from byte arrays. I am assuming this is all 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;
}

Now you just need a structure that will hold your data. It will look something like this:

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

And then all you have to do is populate an instance of PacketHeader with data, and convert it to a byte array like this:

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

var bytes = ToByteArray(packetHeader);

To reverse the process:

var packetHeader p FromByteArray<PacketHeader>(bytes);
Sign up to request clarification or add additional context in comments.

7 Comments

Doing this via struct seems like a mis-step to me, but it would work for fixed-size cases, CPU-endianness permitting. If you're going to do that, though, there are much more direct ways of moving the data around, especially now that we have span-T which allows direct conversion between primitives including to/from byte-spans. Also, even if you keep the Marshal approach, unsafe/fixed over the existing buffer s preferable to an unmanaged alloc
Thank you, it is very clear and looks like it's "almost" doing its job. Only one thing: OP output is 3, 0, 0, 0 (in my case) but it should be 2 bytes (3, 0). Do you know what i should edit?
Make sure that OP is of type UInt16.
Right but including the header, OP should be 2 bytes long only, total output of your code is: 2, 0, 0, 0, 3, 0, 0, 0
Hmm, I'll have to check it when I get home. Sounds like it's aligning on 32 bit boundaries. In the meantime, you can just strip off the last two bytes before you transmit.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.