long.Parse и новое поведение IPAddress при разборе шестнадцатеричного значения в IPAddress C #

1

Вчера я задал вопрос о преобразовании строки HEX в IP и получил ответ здесь: С# конвертировать hex в ip

Проблема в том, что когда я использую функцию

var ip = new IPAddress(long.Parse(ipString, NumberStyles.AllowHexSpecifier));

он возвращает действительный IPAddress, но делает это обратным образом. Например:

Hex String:

c0a8000a

и он должен быть проанализирован следующим образом:

192.168.0.10

Функция long.Parse() возвращает

3232235530

Но мой IP после вызова конструктора IPAddress

10.0.168.192 

вместо правильного. Онлайн-инструменты, такие как http://www.smartconversion.com/unit_conversion/IP_Address_Converter.aspx, работают нормально. Это дело с маленьким или большим концом? Должен ли я перевернуть строку самостоятельно или есть более простой ответ?

Теги:
ip-address
parsing

3 ответа

2
Лучший ответ

Так что небольшое исследование дало, что вы правильно догадались. Это как-то связано с контентом.

Конструктор: IPAddress (long newAddress) ожидает, что значение будет в сетевом порядке байтов, который определен как big-endian.

Я предполагаю, что ваша системная архитектура использует little-endian (как это делают большинство систем intel)

.NET использует контенту базовой системы, поэтому при синтаксическом анализе long такой системы она хранится мало-endian.

Вот почему, когда вы анализируете строку целых чисел через IPAddress.Parse, результат правильный.


Что касается решения.

Eigther вы разбираете свой IPAddress как таковой (по строке):

IPAddress ip = IPAddress.Parse(uint.Parse(ipString, NumberStyles.AllowHexSpecifier).ToString());

Или, чтобы быть более "правильным", вы можете проверить поле BitConverter.IsLittleEndian и перевернуть порядок байтов, если nescessery:

    static IPAddress ParseHexIPAddress(String szIPAddress) {
        uint uiIP = uint.Parse(szIPAddress, System.Globalization.NumberStyles.AllowHexSpecifier);
        IPAddress ip = null;
        if (BitConverter.IsLittleEndian) {
            uint uiIPRev = BitConverter.ToUInt32(BitConverter.GetBytes(uiIP).Reverse().ToArray(), 0);
            ip = new IPAddress(uiIPRev);
        } else {
            ip = new IPAddress(uiIP);
        }
        return ip;
    }
0

По умолчанию номера (в вашем случае длинные) хранятся в формате Little Endian в памяти архитектуры x86, поэтому вы перепутаете IP-адрес. Вы можете проверить это с помощью поля BitConverter.IsLittleEndian. Простое решение состоит в том, чтобы поменять порядок байтов ввода строки и затем проанализировать обратную строку так долго:

string ipString = "c0a8000a";

// Reverse the HEX string byte order
int length = ipString.Length;
char[] reversedChars = new char[length];
for (int i = 0; i < length; i += 2)
{
    reversedChars[i] = ipString[length - i - 2];
    reversedChars[i + 1] = ipString[length - i - 1];
}

string reversedString = new string(reversedChars);

// Parse the reversed byte string
long parsedValue = long.Parse(reversedString, NumberStyles.AllowHexSpecifier);
IPAddress ip = new IPAddress(parsedValue);
0

Как было указано, проблема в том, что вам нужно преобразовать из байта хоста (litte endian) в байтовый порядок сети (большой конец). Вы можете использовать метод IPAddress.HostToNetworkOrder для этого:

var ip = new IPAddress(
  IPAddress.HostToNetworkOrder(
    int.Parse(ipString, NumberStyles.AllowHexSpecifier)
  )
);

Обратите внимание, что вам нужно использовать int.Parse вместо long.Parse для этого, потому что в IPv4-адресе 32 бита, а не 64 бит.

Этот метод не включает преобразование строк или использование других классов, таких как BitConverter для выполнения преобразования.

  • 0
    О, хорошо, я пропустил это. Я думаю, что это удивительно, что конструктор еще не сделал этого, но, по крайней мере, они дали нам возможность быстро преобразовать порядок байтов сами, если мы действительно этого хотим. К тому времени, когда кто-то обнаружил это, 10 человек уже написали метод HostToNetworkOrder .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню