Преобразование 2 байтов в короткий в C # - PullRequest
25 голосов
/ 22 апреля 2011

Я пытаюсь преобразовать два байта в unsigned short, чтобы я мог получить фактическое значение порта сервера.Я основываюсь на этой спецификации протокола в разделе Формат ответа.Я попытался использовать BitConverter.ToUint16 () для этого, но проблема в том, что он не выдает ожидаемое значение.Ниже приведен пример реализации:

int bytesRead = 0;

while (bytesRead < ms.Length)
{
    int first = ms.ReadByte() & 0xFF;
    int second = ms.ReadByte() & 0xFF;
    int third = ms.ReadByte() & 0xFF;
    int fourth = ms.ReadByte() & 0xFF;
    int port1 = ms.ReadByte();
    int port2 = ms.ReadByte();
    int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
    string ip = String.Format("{0}.{1}.{2}.{3}:{4}-{5} = {6}", first, second, third, fourth, port1, port2, actualPort);
    Debug.WriteLine(ip);
    bytesRead += 6;
}

Учитывая один пример данных, скажем, для двухбайтовых значений, у меня есть 105 и 135, ожидаемое значение порта после преобразования должно быть 27015, но вместо этого я получаюзначение 34665 с использованием BitConverter.

Я делаю это неправильно?

Ответы [ 3 ]

28 голосов
/ 22 апреля 2011

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

int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);

В архитектуре с прямым порядком байтов младший байт должен быть вторым в массиве. И, как указывает в комментариях lasseespeholt, вам нужно будет изменить порядок в архитектуре с прямым порядком байтов. Это можно проверить с помощью свойства BitConverter.IsLittleEndian . Или может быть лучшим решением в целом использовать IPAddress.HostToNetworkOrder (сначала преобразуйте значение, а затем вызовите этот метод, чтобы расположить байты в правильном порядке независимо от порядка байтов).

8 голосов
/ 22 апреля 2011

BitConverter делает правильные вещи, вы просто перепутали младший и старший байты - вы можете проверить это с помощью битового сдвига вручную:

byte port1 = 105;
byte port2 = 135;

ushort value = BitConverter.ToUInt16(new byte[2] { (byte)port1, (byte)port2 }, 0);
ushort value2 = (ushort)(port1 + (port2 << 8)); //same output
7 голосов
/ 22 апреля 2011

Чтобы работать как с архитектурой с прямым, так и с младшим порядком байтов, вы должны сделать что-то вроде:

if (BitConverter.IsLittleEndian)
    actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);
else
    actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
...