C # Преобразование из байта [] в структуру. Порядок байтов неверен - PullRequest
4 голосов
/ 16 августа 2010

Я пытался использовать структуру для анализа данных сокета при реализации протокола на основе UDP. И я искал, и я могу использовать эти 2 функции для преобразования между byte [] и 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);
        }
    }

Тогда у меня была такая проблема:

//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

И структура to byte [] точно такая же. 2 байта ushort поменялись местами. Как мне решить эту проблему?

Ответы [ 3 ]

2 голосов
/ 16 августа 2010

Большинство процессоров в настоящее время используют байтовый порядок Little-Endian (младший значащий байт идет первым).Сетевой порядок байтов является традиционным Big-Endian, поэтому вам обычно нужно зеркально отразить порядок байтов.Вы можете проверить порядковый номер системы с помощью System.BitConverter.IsLittleEndian

.Net-эквивалент ntohs (), о котором говорил Франк, расположен (как ни странно) в System.Net.IPAddress.NetworkToHostOrder()

Вы также можете написать свой собственный механизмчитать байты в правильном порядке напрямую, используя сдвиг битов и логическое ИЛИ.

1 голос
/ 16 августа 2010

Проблема связана с порядком байтов short в вашей системе.Посмотрите на этот вопрос о порядке байтов , который может дать некоторые указатели (каламбур непреднамеренный).

Кроме того, я бы предложил сделать BytesToStruct универсальным в типе struct:

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

, поэтому его можно вызывать с

BytesToStruct<S>(bArr)

, а не как в настоящее время

(S)BytesToStruct(bArr, typeof(S))
1 голос
/ 16 августа 2010

Существует различие между порядком сетевых байтов и порядком байтов хоста.

Обычно, по крайней мере, в C вы используете ntohl (), ntohs () и друзей для преобразования порядка сетевых байтов в ваш порядок хостов при чтениииз розетки.

...