- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
static uint ipToUint(byte[] ipBytes)
{
var bConvert = new ByteConverter();
uint ipUint = 0;
int shift = 24; //TODO: указывает количество бит для смещения лево
foreach (byte b in ipBytes)
{
if (ipUint == 0)
{
ipUint = (uint)bConvert.ConvertTo(b, typeof(uint)) << shift;
shift -= 8;
continue;
}
if (shift >= 8)
ipUint += (uint)bConvert.ConvertTo(b, typeof(uint)) << shift;
else
ipUint += (uint)bConvert.ConvertTo(b, typeof(uint));
shift -= 8;
}
return ipUint;
}
Функция конвертирующая массив байтов полученный из IPAddress.Parse("...").GetAddressBytes() в целочисленное представление.
P.S. Чуть выше, видимо, тоже оптимизация, чтобы плюс лишний раз не гонять.
P.P.S. Неужели в шарпе нет готового класса для хранения ip-адресов и парсера айпишников, поддерживающего как IPv4 так и IPv6?
Насчет готового парсера сам искал, нашел такой код:
Но по моему он не правильно работает.
fxd
Если за мгновение до катастрофы бортовой компьютер выдаёт segmentation fault то это С.
А во вторых, при ручном счете можно проверить и увидеть, что значение не верно.
Для 192.168.1.1 должно быть 3232235777, а получается 33663168.
Но в тоже время это как-то странно.
Да кстати, вот проверил, если дописать reverse и toarray то значение больше на единицу чем нужно.
а так, вообще странно, что в с# нет удобного доп. класса а-ля ip::address_v4 / ip::address_v6, с методом типа to_ulong() в v4
притом, что с# конструктор-то сам Int64 принимает, а вот как назад отдать - то только массив
Мы же передаем для парсинга строку, шарпу никто не мешает распарсить ее и вывести не обратный, а привычный порядок байтов.
он поэтому и называется "сетевой порядок байт"
благодаря этому и писюки, и кофеварки, и утюги, утюги за сапогами, сапоги за пирогами, пироги за утюгами, кочерга за кушаком - т.е. всё то, что можно воткнуть в порт свича, или чем поднасрать в wi-fi эфир - может общаться друг с другом независимо от своей платформы и собственного порядка байт
little endian использует ваша машина для рассчётов.
Да, не сразу очевидно, почему оно называется именно так.
Мы отдаем в парсер строку, на выходе получаем массив байтов, там не используются те низкоуровневые представления о которых вы говорите.
> Все очевидно.
я всего лишь сказал, что IPAddress.Parse().GetAddressBytes() возвращает данные в big-endian, а не в little-endian
просто если ты будешь просто рассматривать байты [с0 а8 01 01] как uint32 на little-endian платформе, то получится, что с0 - младший байт, а 01 - старший, и вот ты и получил "ошибочное" представление 0x0101a8c0
почитай уже на педивикии хоть что нибудь про big- и little-endian
Вообще то там будет {1,1,168,192}
вот я к чему. Что нельзя было для парсера строк сделать блин big-endian? Еще раз для упрямых, мы отдаем туда строку, блин строку она никак не связана с архитектурой компа и.т.д. Массив элементов типа byte - это не куча байтов!
вот переделанный пример от @roman-kashitsyn
http://ideone.com/sBm4Yr
В общем косяк в том, что битконвертер конвертирует этот красивый массив { 192, 168, 1, 1 } в неверное целочисленное представление.
Что бы представление было верным нужно сначала перевернуть этот массив, потом создать из него новый массив и только потом посылать битконвертеру. Плюс позже еще и еденичку отнять. Ну вот зачем эти тацны с бубном когда с помощью простого метода или того-же linq это можно сделать быстрее, проще и понятнее. Вот, что я хотел сказать в самом начале.(Для того, что бы целочисленное представление было верным)
А вы пристали тут ко мне со своими байтовыми порядками! Еще запутали и увели в глушь.
https://ideone.com/G0qSPF
Вопрос в том, что он распарсит не в то число которое должно быть по идее. Что бы получить нужное число приходится допиливать костыли.
>не в то число которое должно быть по идее
Число то, просто оно big-endian, выше уже писали почему.
Я теперь попробую еще раз попытаться объяснить.
Массив полученный из функции будет выглядеть так, да? {192, 168, 1, 1}
Тут мы все согласны.
Но вот битконфертер при создании числа пойдет не от головы, а с хвоста. И потому мы получим значение отличное от того, которое вроде бы должны получить.
В общем я против того варианта, с использованием битконвертера, когда нам важно получить целочисленное представление ip-адреса.
Используй LINQ, ёпта.
http://stackoverflow.com/a/2473895
Не слушай всяких смутьянов, которые лезут со своими индейцами.
LINQ решит любые проблемы.
но что-то по ссылке не вижу AsParallel, что за однопоточное говнецо эти гуры там советуют?
Главное что бы результат не отличался от того, который нужен.
Вот например можно даже из браузера обратится в такому эквиваленту ip адреса и браузер его распарсит.
Предпочитаю двухоперандный асм-стайл.
(для любителей антроллить.)
uint res=0
res|=a[0]; res<<=8;
res|=a[1]; res<<=8;
res|=a[2]; res<<=8;
res|=a[3];
0x0201a8c0 == 192.168.1.2
big-endian же
Ну не верное же значение.
Мы, люди,европейцы, считаем и читаем слева на право.
Так что никакие значения отличные от 3232235777 быть не могут.
Значение должно быть 3232235777 и это проблемы шарпа, не компа.
Ну собственно в описании к ГК написано, что был использован класс IPAddress и его метод Parse. Ребята просто решили IP в uint перевести, зачем они это делают,я не знаю. Возможно хотят в базе в таком виде хранить, может выборки по диапозонам ip из базы делать будут.
Нашел на одном из форумов.
http://stackoverflow.com/questions/4636164/convert-ip-address-into-int-ie-inet-aton-in-c