Преобразование 2 байтов в Short в С#
Я пытаюсь преобразовать два байта в 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.
Я делаю это неправильно?
Ответы
Ответ 1
Если вы измените значения в вызове BitConverter, вы получите ожидаемый результат:
int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);
В малоинтенсивной архитектуре младший байт должен быть вторым в массиве. И как отмечает lasseespeholt в комментариях, вам нужно будет отменить порядок в архитектуре большого конца. Это можно проверить с помощью свойства BitConverter.IsLittleEndian. Или может быть лучшим решением в целом использовать IPAddress.HostToNetworkOrder (сначала преобразовать значение, а затем вызвать этот метод, чтобы поместить байты в правильном порядке независимо от его соответствия).
Ответ 2
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
Ответ 3
Чтобы работать как с маленькой, так и с большой архитектурой, вы должны сделать что-то вроде:
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);