Вчера я задал вопрос о преобразовании строки 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, работают нормально. Это дело с маленьким или большим концом? Должен ли я перевернуть строку самостоятельно или есть более простой ответ?
Так что небольшое исследование дало, что вы правильно догадались. Это как-то связано с контентом.
Конструктор: 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;
}
По умолчанию номера (в вашем случае длинные) хранятся в формате 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);
Как было указано, проблема в том, что вам нужно преобразовать из байта хоста (litte endian) в байтовый порядок сети (большой конец). Вы можете использовать метод IPAddress.HostToNetworkOrder
для этого:
var ip = new IPAddress(
IPAddress.HostToNetworkOrder(
int.Parse(ipString, NumberStyles.AllowHexSpecifier)
)
);
Обратите внимание, что вам нужно использовать int.Parse
вместо long.Parse
для этого, потому что в IPv4-адресе 32 бита, а не 64 бит.
Этот метод не включает преобразование строк или использование других классов, таких как BitConverter
для выполнения преобразования.
HostToNetworkOrder
.