开发者

C# Converting from byte[] to struct. The byte order is wrong

I was trying to use a struct to parse socket data when implement a UDP based protocol. And I searched and I can use these 2 functions to convert between byte[] and struct:

 byte[] StructToBytes(object structObj)
    {
        int size = Marshal.SizeOf(structObj);
        IntPtr buffer =开发者_运维技巧 Marshal.AllocHGlobal(size);
        try
        {
            Marshal.StructureToPtr(structObj, buffer, false);
            byte[] bytes = new byte[size];
            Marshal.Copy(buffer, bytes, 0, size);
            return bytes;
        }
        finally
        {
            Marshal.FreeHGlobal(buffer);
        }

    }

    static object BytesToStruct(byte[] bytes, Type strcutType, int offset = 0)
    {
        int size = Marshal.SizeOf(strcutType);
        IntPtr buffer = Marshal.AllocHGlobal(size);
        try
        {
            Marshal.Copy(bytes, offset, buffer, size);
            return Marshal.PtrToStructure(buffer, strcutType);
        }
        finally
        {
            Marshal.FreeHGlobal(buffer);
        }
    }

Then I had this problem:

//I defined a simple struct with an ushort member
    [StructLayout(LayoutKind.Sequential, Pack = 2)]
    struct S
    {
        public ushort a;
    }

    //Then I define a byte[]
    byte[] bArr;
    bArr[0] = 0;
    bArr[1] = 1;

    //Convert to struct
    S s = (S)BytesToStruct(bArr, typeof(S));
    //Then s.a = 0x0100 not 0x0001

And struct to byte[] is just the same. The 2 bytes of ushort are reversed. How do I solve this problem?


Most processors these days use Little-Endian byte ordering (Least significant byte comes first). Network byte ordering is traditional Big-Endian, so you usually need to mirror the byte order. You can check the endianness of the system with System.BitConverter.IsLittleEndian

The .Net equivalent of ntohs() Frank mentioned is located (oddly) at System.Net.IPAddress.NetworkToHostOrder()

You could also write your own mechanism to read the bytes in the correct order directly, using bit shifting and logical OR.


There's a difference between network byte order and host byte order.

Typically, in C at least, you use ntohl(), ntohs() and friends to convert network byte order to your host order when reading from a socket.


The problem is to do with the endianness of short on your system. Have a look at this question about endianness, which may provide some pointers (pun unintentional).

Also, I would suggest making BytesToStruct generic in the type of the struct:

static S BytesToStruct<S>(byte[] bytes, int offset = 0)

so it could be called with

BytesToStruct<S>(bArr)

rather than as at present

(S)BytesToStruct(bArr, typeof(S))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜