Вопрос

В документации к оборудованию, которое позволяет нам управлять им через 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 символов?

Это было полезно?

Решение

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

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

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

Другие советы

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

IPAddress.NetworkToHostOrder(...)

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

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

bool le = BitConverter.IsLittleEndian;

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

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

Re конкретный UDP / IP ...?

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

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

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

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

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

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);

Я играю с упакованными данными в 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}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top