C # little endian или big endian? - PullRequest
       36

C # little endian или big endian?

59 голосов
/ 20 октября 2008

В документации на оборудование, которое позволяет нам управлять им через UDP / IP, Я нашел следующий фрагмент:

В этом протоколе связи DWORD - это 4-байтовые данные, WORD - это 2-байтовые данные, BYTE - это однобайтовые данные. Формат хранения имеет порядок байтов, то есть данные размером 4 байта (32 бита) хранятся как: d7-d0, d15-d8, d23-d16, d31-d24; двухбайтовые (16-битные) данные хранятся как: d7-d0, d15-d8.

Мне интересно, как это переводится на C #? Должен ли я конвертировать вещи перед отправкой? Например, если я хочу отправить 32-разрядное целое число или строку из 4 символов?

Ответы [ 6 ]

77 голосов
/ 20 октября 2008

C # сам по себе не определяет порядок байтов. Однако, когда вы конвертируете в байты, вы делаете выбор. Класс BitConverter имеет поле IsLittleEndian , чтобы сообщить вам, как оно будет себя вести, но оно не дает выбора. То же самое касается BinaryReader / BinaryWriter.

Моя MiscUtil библиотека имеет класс EndianBitConverter, который позволяет вам определять порядок байтов; Есть аналогичные эквиваленты для BinaryReader / Writer. Боюсь, нет руководства по использованию в Интернете, но они тривиальны:)

(EndianBitConverter также имеет часть функциональности, которой нет в обычном BitConverter, которая должна выполнять преобразования на месте в байтовом массиве.)

43 голосов
/ 20 октября 2008

Вы также можете использовать

IPAddress.NetworkToHostOrder(...)

Для коротких, int или long.

10 голосов
/ 20 октября 2008

Re-little-endian, краткий ответ (для этого мне нужно что-то сделать) - "вероятно, нет, но это зависит от вашего оборудования". Вы можете проверить с помощью:

bool le = BitConverter.IsLittleEndian;

В зависимости от того, что это говорит, вы можете обратить вспять части ваших буферов. В качестве альтернативы, у Джона Скита есть конвертеры с прямым порядком байтов здесь (ищите EndianBitConverter).

Обратите внимание, что itaniums (например) имеют порядок байтов. Большинство Intel имеют младший порядок.

Относительно конкретного UDP / IP ...?

3 голосов
/ 20 октября 2008

Вам необходимо знать о порядке байтов в сети, а также о бесконечности процессора.

Обычно для передачи данных по протоколу TCP / UDP вы всегда преобразуете данные в сетевой порядок байтов, используя функцию htonsntohs, и связанные с ними функции).

Обычно сетевой порядок имеет порядок с прямым порядком байтов, но в этом случае (по какой-то причине!) Связь не имеет порядкового номера, поэтому эти функции не очень полезны. Это важно, поскольку вы не можете предполагать, что внедренные ими UDP-соединения соответствуют каким-либо другим стандартам, это также усложняет жизнь, если у вас архитектура с прямым порядком байтов, поскольку вы просто не можете обернуть все с помощью htons, как следует: 1010 *

Однако, если вы работаете с архитектурой Intel x86, значит, вы уже в порядке байтов, поэтому просто отправляйте данные без преобразования.

0 голосов
/ 10 сентября 2015

Я играю с упакованными данными в UDP Multicast, и мне нужно было что-то переупорядочить октеты UInt16, так как я заметил ошибку в заголовке пакета (Wireshark), поэтому я сделал это:

    private UInt16 swapOctetsUInt16(UInt16 toSwap)
    {
        Int32 tmp = 0;
        tmp = toSwap >> 8;
        tmp = tmp | ((toSwap & 0xff) << 8);
        return (UInt16) tmp;
    }

В случае UInt32,

    private UInt32 swapOctetsUInt32(UInt32 toSwap)
    {
        UInt32 tmp = 0;
        tmp = toSwap >> 24;
        tmp = tmp | ((toSwap & 0xff0000) >> 8);
        tmp = tmp | ((toSwap & 0xff00) << 8);
        tmp = tmp | ((toSwap & 0xff) << 24);
        return tmp;
    }

Это только для тестирования

    private void testSwap() {
        UInt16 tmp1 = 0x0a0b;
        UInt32 tmp2 = 0x0a0b0c0d;
        SoapHexBinary shb1 = new SoapHexBinary(BitConverter.GetBytes(tmp1));
        SoapHexBinary shb2 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt16(tmp1)));
        Debug.WriteLine("{0}", shb1.ToString());
        Debug.WriteLine("{0}", shb2.ToString());
        SoapHexBinary shb3 = new SoapHexBinary(BitConverter.GetBytes(tmp2));
        SoapHexBinary shb4 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt32(tmp2)));
        Debug.WriteLine("{0}", shb3.ToString());
        Debug.WriteLine("{0}", shb4.ToString());
    }

из которого был вывод:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
0 голосов
/ 08 ноября 2012

Если вы анализируете и производительность не критична, рассмотрите этот очень простой код:

private static byte[] NetworkToHostOrder (byte[] array, int offset, int length)
{
    return array.Skip (offset).Take (length).Reverse ().ToArray ();
}

int foo = BitConverter.ToInt64 (NetworkToHostOrder (queue, 14, 8), 0);
...