пятница, 15 октября 2010 г.

Перебор IP ver4 адресов C#

Возникла такая задача, привычным движением руки взял и загуглил, может я еще плохо искать умею. но… не нашел, тот кровавый ###### который советуют люди на различных форумах заставил меня лить горючие слёзы. Пришлось делать все самому.


Нужно игнорировать советы вроде «Работай как со строкой», так как IP адрес — не строка, и выглядит так, как выглядит только по одной причине — читабельность.

IPv4 адрес — набор из 32х бит. Подробнее можно узнать в википедии.

Функция свертывания массива байтов в четырехбайтное целое.


        private int CompressByteArray(byte[] bytes)
        {
            /*Проверяем является ли массив подходящим для свертывания в int*/
            if (bytes.Length != 4) throw new FormatException("Wrong IPv4 address");
            int retval = 0; byte bit_shift = 0;
            for (int i = bytes.Length - 1; i >= 0; i--)
            {
                /*Прибавляем к финальному значению байты со сдвигом,
                  зависящим от текущего элемента массива*/

                retval += ((int)bytes[i]) << bit_shift;
                bit_shift += 8;
            }
            return retval;
        }
       


Этот и весь следующий код предназначен исключительно для ipv4, не было желания мучить себя хранением 128 битовых адресов, по крайней мере в этот раз.

Функция развертывания целого числа в массив байтов.


        private byte[] DecompressByteArray(int ip)
        {
            //Разбиваем целое число на байты          
            var bytes = BitConverter.GetBytes(ip);  
            //Разворачиваем в нужную последовательность    
            Array.Reverse(bytes);
            return bytes;
        }
       


Ну и наконец та функция, которая и будет выводить список всех адресов диапазона.


        public IPAddress[] ExpandIpRange(IPAddress RangeFirst, IPAddress RangeLast)
        {
            /*Сворачиваем байты адреса в целое число*/
            var start_ip = (uint)(CompressByteArray(RangeFirst.GetAddressBytes()));
            /*Расчитываем дельту адресов(можно простым вычитанием, но xor логичнее и быстрее)*/
            var delta = (uint)(CompressByteArray(RangeLast.GetAddressBytes()) ^ start_ip);
            IPAddress[] retval = new IPAddress[delta];
            /*Создаем список адресов диапазона
              перебор осуществляется простым приращением*/

            for (uint i = 0; i <= delta; i++)  
                /*Разворачиваем число в массив байтов
                  Создаем экземпляр Ip адреса и передаем массив в конструктор
                  Добавляем адрес в список*/

                try { retval[i] = new IPAddress(DecompressByteArray((int)(start_ip + i))); }
                catch { continue; }
            return retval;
        }
       


Использование. Предположим, что у нас консольное приложение, функции описанные выше можно добавить сразу перед/после main.


        static void Main(string[] args)
        {
            IPAddress addr = new IPAddress(new byte[] { 17, 0, 0, 1 });
            IPAddress addr2 = new IPAddress(new byte[] { 17, 0, 2, 125 });
            var t = new TestovyPoligon.Program();
            var ips = t.ExpandIpRange(addr, addr2);
            foreach (var ip in ips)
                Console.WriteLine(ip.ToString());
        }
       

______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru

5 комментариев:

Анонимный комментирует...

спасибо друг!

Анонимный комментирует...

хрень! попробуй получить диапазон адресов, наспример 192.168.0.222 - 192.168.0.225 и посмотри что получится.

Unknown комментирует...

"хрень!"
Не затруднит вывод показать? У меня пока нет возможности проверить код

Анонимный комментирует...

извиняюсь за "хрень!". Я уже по своему сделал. Может и коряво, но работает правильно.

Unknown комментирует...

Я и не обижался, кинь как сделал, и как мое работало, я имею большое желание исправить ошибку