В самом грубом представлении IP-адрес – это просто число. В случае протокола IPv4 IP-адрес– это 32-разрядное целое число, используемое для представления хоста в сети. То есть существует 2 32 возможных IPv4 адреса – от 0 до 4 294 967 295. IPv4-адреса записывают в виде четырех октетов – целых чисел, разделенных точками:
Каждый октет – это один байт, число от 0 до 255. То есть максимальный адрес равен 255.255.255.255 , а минимальный – 0.0.0.0 .
Далее мы рассмотрим, как модуль ipaddress выполняет преобразования адреса так, что нам не приходится отвлекаться на строение адреса.
Получим внешний IP -адрес нашего компьютера для работы с ним в командной строке. В Linux это делается так:
Этот запрос узнает наш IP-шник на сайте ifconfig.me. Сайт также выдает множество другой полезной информации о вашем сетевом подключении.
Теперь откроем интерпретатор Python. Чтобы создать объект Python с инкапсулированным адресом, создадим класс IPv4Address :
Передача строки “220.14.9.37” в конструктор IPv4Address – наиболее распространенный подход, но класс может принимать и другие типы:
Адрес можно распаковать в требуемую форму:
Экземпляры IPv4Address являются хэшируемыми и могут использоваться в качестве ключей словаря:
Класс IPv4Address также реализует методы, позволяющие проводить сравнения:
Можно использовать любой стандартный оператор сравнения целочисленных значений адресных объектов.
Сеть – это набор IP-адресов. Сети описываются и отображаются как непрерывные диапазоны адресов. Например, сеть может соответствовать диапазону 192.4.2.0 – 192.4.2.255 , т. е. включать 256 адресов. Если нужно это отобразить в краткой форме, используется нотация CIDR.
В CIDR сеть определяется с помощью сетевого адреса и префикса <network_address>/<prefix> :
В данном случае префикс равен 24. Префикс – это количество ведущих битов, соответствующих входящим в сеть адресам. Ведущие биты отсчитываются слева направо.
Пример: входит ли адрес 192.4.2.12 в сеть 192.4.2.0/24?
Ответ: да, так как ведущие 24 бита адреса 192.4.2.12 – это первые три октета: 192.4.2 . Последний октет соответствует последним 8 битам 32-битного IP-адреса.
Воспользуемся netmask для маскирования битов в сравниваемых адресах.
На рисунке ниже показано, как сравниваются ведущие биты, чтобы определить, является ли адрес частью сети.
Побитовое сравнение
Последние 8 бит в 192.4.2.12 маскируются нулем и игнорируются при сравнении.
Рассмотрим еще один важный тип адреса – широковещательный.
Это единственный адрес, который может использоваться для связи со всеми хостами сети:
Чаще всего вы будете сталкиваться с длиной префикса кратной 8.
Распространенные подсети
Любое целое число от 0 до 32 является допустимым, но такой вариант встречается реже:
Класс IPv4Network позволяет перебирать отдельные адреса в цикле for:
Инструмент net.hosts() возвращает генератор, выдающий адреса, исключая сетевые и широковещательные:
Подсеть – это часть IP-сети:
В коде выше small_net содержит 16 адресов, а big_net – 65 536.
Распространенный способ разбиения на подсети – это увеличение длины префикса на 1:
Разбиение сети
К счастью, IPv4Network расчеты подсетей поддерживаются встроенным методом subnets() :
В передаваемом subnets() аргументе можно задать, каким должен быть новый префикс:
Администрация адресного пространства Интернет (Internet Assigned Numbers Authority, IANA) совместно с Инженерном советом Интернета (Internet Engineering Task Force, IETF) осуществляют надзор за распределением диапазонов адресов. Реестр подобных адресов – важная таблица, которая описывает, для каких целей зарезервированы диапазоны IPv4-адресов.
К примеру, это частные IP-адреса, используемые для внутренней связи между устройствами в сети, не требующей подключения к интернету:
Зарезервированные диапазоны
Случайным образом выберем адрес – 10.243.156.214 . Относится ли этот адрес к приватным? Для этого проверим, попадает ли он в диапазон cети 10.0.0.0/8 :
Другой специальный тип адреса – это локальный адрес связи, состоящий из блока 169.254.0.0/16 . Примером может служить Amazon Time Sync Service , доступный для инстансов AWS EC2 по адресу 169.254.169.123 . Данный пул также использует Windows для выдачи адресов сетевым адаптерам при отсутствии интернета от провайдера.
Модуль ipaddress предоставляет набор свойств для проверки того, относится ли адрес к специальным:
Вот еще несколько зарезервированных сетей:
- 0.0.0.0/8 – адреса источников пакетов «своей» сети;
- 127.0.0.0/8 – используется для локального хоста;
- 169.254.0.0/16 – внутренние адреса;
- 198.18.0.0/15 – для бенчмаркинга сетей.
В дополнение к хорошо документированному API, исходный код CPython и класс IPv4Address показывают некоторые отличные идеи, как улучшить собственный код.
Компоновщик
Модуль ipaddress использует преимущества шаблона проектирования «Компоновщик». Класс IPv4Address представляет собой компоновщик, который оборачивает обычное целое число.
Каждый экземпляр IPv4Address имеет атрибут _ip , число типа int . Многие свойства и методы класса определяются значением этого атрибута:
Атрибут _ip отвечает за создание int(addr) . Цепочка вызовов выглядит следующим образом:
Цепочка вызовов в компоновщике
Продемонстрируем силу ._ip путем расширения класса IPv4Address :
Добавление .__and__() позволяет использовать бинарный оператор & , чтобы применять маску к IP-адресу:
Метод __and__() позволяет использовать либо другой IPv4Address, либо непосредственно int в качестве маски. Поскольку MyIPv4 является подклассом IPv4Address, проверка isinstance() в данном случае вернет T rue .
Помимо перегрузки оператора, есть возможность добавить новые свойства:
В методе binary_repr (строка 8), используется .packed для преобразования IP-адреса в массив байтов, который затем форматируется, как строковое представление бинарной формы.
В from _ binary _ repr , вызов int ( re . sub ( r “[^01]”, “”, binary _ repr ), 2) (строка 14) состоит из двух частей:
- удаление из входящей строки всего, кроме нулей и единиц;
- анализ результата с помощью int(<string>, 2) .
Методы binary_repr() и from_binary_repr() позволяют проводить двустороннюю конвертацию:
Таким образом, мы разобрали несколько способов использования преимуществ шаблона IP-as-integer, который может помочь расширить функциональность IPv4Address с небольшим количеством дополнительного кода.
Заключение
Если вам нравится язык Python и вы хотите детально овладеть стандартной библиотекой, у нас есть множество родственных публикаций: