1. C# / Говнокод #13063

    +131

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 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() в целочисленное представление.

    Запостил: neeedle, 29 Мая 2013

    Комментарии (70) RSS

    • Ну не стыдно привязывать программу к ipv4? Не на Си для контроллеров же пишут, а на высокоуровневом шарпе...
      if (shift >= 8)
          ipUint += (uint)bConvert.ConvertTo(b, typeof(uint)) << shift;
      else
          ipUint += (uint)bConvert.ConvertTo(b, typeof(uint));
      Оптимизация. Сдвиг же работает дольше чем сравнение и переход.

      P.S. Чуть выше, видимо, тоже оптимизация, чтобы плюс лишний раз не гонять.
      P.P.S. Неужели в шарпе нет готового класса для хранения ip-адресов и парсера айпишников, поддерживающего как IPv4 так и IPv6?
      Ответить
      • Не знаю насчет оптимизации, но на глаз могу сказать, что данный код можно упростить до такого состояния.

        byte[] ipBytes = IPAddress.Parse(address).GetAddressBytes();
        
        
                        uint ipUint = 0;
                        int shift = 24;
        
                        foreach (var ipByte in ipBytes)
                        {
                            if (ipUint == 0)
                            {
                                ipUint = (uint) ipByte << shift;
                            }
                            else
                            {
                                ipUint += (uint) ipByte << shift;
                            }
                            shift -= 8;
                        }
                        return ipUint;


        Насчет готового парсера сам искал, нашел такой код:
        int intAddress = BitConverter.ToInt32(IPAddress.Parse(address).GetAddressBytes(), 0);

        Но по моему он не правильно работает.
        Ответить
        • if (ipUint == 0)
          {
              ipUint = (uint) ipByte << shift;
          }
          else
          {
              ipUint += (uint) ipByte << shift;
          }
          shift -= 8;
          легким движением руки превращается в
          ipUint += (uint) ipByte << shift;
          shift -= 8;
          Ну не нужны там условия, не нужны.
          Ответить
          • А, да, тем более.
            Ответить
          • ntohl(*reinterpret_cast<uint32_t*>(bytes ))
            Ответить
            • Экое крестоблядство.
              Ответить
              • чем крестоблядство хуже шарпоблядства?
                Ответить
                • Ничем. Все блядства эквивалентны ;)
                  Ответить
                  • Назову это Гипотеза Люра-Борманда.
                    Ответить
                    • А как должен выглядеть эксперимент, подтверждающий эту гипотезу? :o
                      Ответить
                      • Если вы летите в космическом корабле и не видите сорцов бортового софта, вы не можете сказать, на каком языке написан этот глюкавый кусок ... пшшшшш..... связь c бортом потеряна ...
                        Ответить
                        • > Если вы равномерно и прямолинейно летите в космическом корабле
                          fxd
                          Ответить
                        • Если вы ни с того, ни с сего врезаетесь в стену, то это жаба.
                          Если за мгновение до катастрофы бортовой компьютер выдаёт segmentation fault то это С.
                          Ответить
        • Все работает
          UInt32 ip1 = BitConverter.ToUInt32(IPAddress.Parse("255.255.1.0").GetAddressBytes(), 0); //0x0001ffff
          String ip2 = new IPAddress(BitConverter.GetBytes(ip1)).ToString(); //255.255.1.0
          Ответить
          • Это тоже видел, но вот вы попробуйте сконвертировать 192.168.1.1 и 192.168.1.2, посмотрите на сколько они отличаются.
            А во вторых, при ручном счете можно проверить и увидеть, что значение не верно.

            Для 192.168.1.1 должно быть 3232235777, а получается 33663168.
            Ответить
            • и что, даже никаких догадок почему так?
              Ответить
              • Я знаю почему так, но мне кажется, что лучше свой метод написать, чем воротить лапшу добавляя reverse и toarray.
                Но в тоже время это как-то странно.

                Да кстати, вот проверил, если дописать reverse и toarray то значение больше на единицу чем нужно.
                Ответить
                • http://msdn.microsoft.com/ru-ru/library/x1886wea.aspx

                  а так, вообще странно, что в с# нет удобного доп. класса а-ля ip::address_v4 / ip::address_v6, с методом типа to_ulong() в v4
                  притом, что с# конструктор-то сам Int64 принимает, а вот как назад отдать - то только массив
                  Ответить
                  • Опа, не знал.
                    Ответить
                  • Хотя поспешил я вас плюсовать.
                    Мы же передаем для парсинга строку, шарпу никто не мешает распарсить ее и вывести не обратный, а привычный порядок байтов.
                    Ответить
                    • что значит привычный? для сетевых значений привычный - big-endian
                      он поэтому и называется "сетевой порядок байт"
                      благодаря этому и писюки, и кофеварки, и утюги, утюги за сапогами, сапоги за пирогами, пироги за утюгами, кочерга за кушаком - т.е. всё то, что можно воткнуть в порт свича, или чем поднасрать в wi-fi эфир - может общаться друг с другом независимо от своей платформы и собственного порядка байт
                      Ответить
                      • Здрасьте приехали, на выходе того метода получаем little-endian.

                        BitConverter.ToUInt32(IPAddress.Parse("255.255.1.0").GetAddressBytes(), 0);
                        Ответить
                        • big endian приходит из сети.
                          little endian использует ваша машина для рассчётов.
                          Да, не сразу очевидно, почему оно называется именно так.
                          Ответить
                          • Все очевидно.
                            Мы отдаем в парсер строку, на выходе получаем массив байтов, там не используются те низкоуровневые представления о которых вы говорите.
                            Ответить
                            • >> Здрасьте приехали, на выходе того метода получаем little-endian
                              > Все очевидно.
                              я всего лишь сказал, что IPAddress.Parse().GetAddressBytes() возвращает данные в big-endian, а не в little-endian
                              Ответить
                              • Это я понял, я не могу понять почему?
                                Ответить
                                • чем тебе не нравится для айпишника 192.168.1.1 получить массив { 192, 168, 1, 1 }? очень даже логично и красиво
                                  просто если ты будешь просто рассматривать байты [с0 а8 01 01] как uint32 на little-endian платформе, то получится, что с0 - младший байт, а 01 - старший, и вот ты и получил "ошибочное" представление 0x0101a8c0
                                  почитай уже на педивикии хоть что нибудь про big- и little-endian
                                  Ответить
                                  • >>{ 192, 168, 1, 1 }?

                                    Вообще то там будет {1,1,168,192}
                                    вот я к чему. Что нельзя было для парсера строк сделать блин big-endian? Еще раз для упрямых, мы отдаем туда строку, блин строку она никак не связана с архитектурой компа и.т.д. Массив элементов типа byte - это не куча байтов!
                                    Ответить
                                    • с какого перепугу там будет {1, 1, 168, 192}?
                                      вот переделанный пример от @roman-kashitsyn
                                      http://ideone.com/sBm4Yr
                                      Ответить
                                      • Ой. Чего-то я перепутал кажись.
                                        Ответить
                                      • Так, я восстановил ход своих мыслей.
                                        В общем косяк в том, что битконвертер конвертирует этот красивый массив { 192, 168, 1, 1 } в неверное целочисленное представление.
                                        Что бы представление было верным нужно сначала перевернуть этот массив, потом создать из него новый массив и только потом посылать битконвертеру. Плюс позже еще и еденичку отнять. Ну вот зачем эти тацны с бубном когда с помощью простого метода или того-же linq это можно сделать быстрее, проще и понятнее. Вот, что я хотел сказать в самом начале.(Для того, что бы целочисленное представление было верным)
                                        А вы пристали тут ко мне со своими байтовыми порядками! Еще запутали и увели в глушь.
                                        Ответить
                                        • блять... и ведь потом эти же люди нахуярят мне письмецо в виде http://govnokod.ru/13070
                                          Ответить
                                        • Попробуем еще раз
                                          https://ideone.com/G0qSPF
                                          Ответить
                                          • Господи, да вопрос не в том, что он распарсит в int и обратно без изменения.
                                            Вопрос в том, что он распарсит не в то число которое должно быть по идее. Что бы получить нужное число приходится допиливать костыли.
                                            Ответить
                                            • Ну Вы хотя-бы код по ссылке посмотрели. Причем здесь туда и обратно?

                                              >не в то число которое должно быть по идее
                                              Число то, просто оно big-endian, выше уже писали почему.
                                              Ответить
                                              • Смешались кони, люди...
                                                Я теперь попробую еще раз попытаться объяснить.
                                                Массив полученный из функции будет выглядеть так, да? {192, 168, 1, 1}
                                                Тут мы все согласны.
                                                Но вот битконфертер при создании числа пойдет не от головы, а с хвоста. И потому мы получим значение отличное от того, которое вроде бы должны получить.
                                                В общем я против того варианта, с использованием битконвертера, когда нам важно получить целочисленное представление ip-адреса.
                                                Ответить
                                                • Да там будет {192, 168, 1, 1}, так как big-endian, да, BitConverter работает с little-endian, именно поэтому я использовал метод IPAddress.NetworkToHostOrder, которые конвертит be -> le. Вины BitConverter'a здесь никакой нет
                                                  Ответить
                                                • Битконвертер не виноват. Виноват интел и только интел. Запустишь на машине с BigEndian - получишь то, что хотел.
                                                  Ответить
                            • Да не парься ты.
                              Используй LINQ, ёпта.
                              http://stackoverflow.com/a/2473895
                              Не слушай всяких смутьянов, которые лезут со своими индейцами.
                              LINQ решит любые проблемы.
                              Ответить
                              • воот, LINQ - первый дельный совет по теме
                                но что-то по ссылке не вижу AsParallel, что за однопоточное говнецо эти гуры там советуют?
                                Ответить
                              • И где тут LINQ, собственно? Написал var уже LINQ? Да, может var тип и был придуман специально для LINQ запросов, но только наличие var не делает запрос LINQ, не находите?
                                Ответить
              • а я ведь сверху зелёным оставил жирную подсказку
                Ответить
                • он вставил твой код и он не заработал!
                  Ответить
                • Низкий вам поклон.
                  Ответить
                  • чем плох вообще (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]
                    Ответить
                    • А что находится в a[0] - 192 или 1?(если адрес - 192.168.1.1)
                      Ответить
                      • почти уверен, что 192
                        Ответить
                        • Ну вроде бы ничем.
                          Главное что бы результат не отличался от того, который нужен.
                          Вот например можно даже из браузера обратится в такому эквиваленту ip адреса и браузер его распарсит.
                          Ответить
                          • Ну если отличается - перевернете [0] [1] [2] [3] ;)
                            Ответить
                    • Шарп даже догадывается расширить тип при сдвиге, но приходится кастить int к uint
                      http://ideone.com/Lf04Fg
                      Ответить
                    • Запись в одну строчку некошерна. Так никакого монитора не хватит.
                      Предпочитаю двухоперандный асм-стайл.
                      (для любителей антроллить.)
                      uint res=0
                      res|=a[0]; res<<=8;
                      res|=a[1]; res<<=8;
                      res|=a[2]; res<<=8;
                      res|=a[3];
                      Ответить
            • 0x0101a8c0 == 192.168.1.1
              0x0201a8c0 == 192.168.1.2
              big-endian же
              Ответить
              • Да, знаю.
                Ну не верное же значение.
                Ответить
                • В каком месте оно неверное?
                  Ответить
                  • В обратном порядке считается, вот в каком.
                    Мы, люди,европейцы, считаем и читаем слева на право.
                    Так что никакие значения отличные от 3232235777 быть не могут.
                    Ответить
                    • Создатели архитектур x86 и x86_64 думают иначе.
                      Ответить
                      • Они могут думать как угодно, но если бы я писал класс который работает с ip-адресами то я бы это учитывал.
                        Значение должно быть 3232235777 и это проблемы шарпа, не компа.
                        Ответить
                    • IPAddress.NetworkToHostOrder если так сильно хочется
                      Ответить
      • >>P.P.S. Неужели в шарпе нет готового класса для хранения ip-адресов и парсера айпишников, поддерживающего как IPv4 так и IPv6?
        Ну собственно в описании к ГК написано, что был использован класс IPAddress и его метод Parse. Ребята просто решили IP в uint перевести, зачем они это делают,я не знаю. Возможно хотят в базе в таком виде хранить, может выборки по диапозонам ip из базы делать будут.
        Ответить
        • Ну целочисленное значение, насколько я знаю, меньше чем строка и его легче в базе хранить, но этот код использовался для того, что бы вывести диапазон ip адресов.
          Нашел на одном из форумов.
          Ответить
    • public int ToInteger(int A, int B, int C, int D)
      {
          return Convert.ToInt32((A* Math.Pow(256, 3)) + (B* Math.Pow(256, 2)) + (C* 256) + D);
      }

      http://stackoverflow.com/questions/4636164/convert-ip-address-into-int-ie-inet-aton-in-c
      Ответить

    Добавить комментарий