Задание №10. Адрес сети, узлы и подсчёт IP-адресов
Как маска разделяет адрес на две части, как найти сеть и последний узел и как посчитать адреса с условием на число единиц.
В задании даны IP-адрес и маска сети. Маска показывает, какие биты одинаковы у всех адресов этой сети, а какие могут меняться. По этой границе находится адрес сети, последний адрес компьютера или количество адресов с нужным числом единиц. Сначала определяется общая часть адресов, затем выполняется действие из вопроса.
Что показывает маска
В этих задачах используется IPv4-адрес: четыре числа от 0 до 255 через точки. Каждое число представляет октет, то есть восемь битов. Например, последний октет адреса 96.224.188.76 записывается как 76_{10}=01001100_2. Начальный ноль сохраняет длину в восемь разрядов.
Маска тоже содержит 32 бита: сначала идут единицы, затем нули. Единицы отмечают сетевую часть, общую для всех адресов подсети; нули — узловую часть, которая различает адреса внутри неё. Подсеть здесь — весь набор адресов с этой общей начальной частью.
Адрес сети получается побитовым И адреса и маски. Это сохраняет сетевую часть и обнуляет узловую. Для октета маски 255 исходный октет сохраняется, для 0 — превращается в 0. Остальные значения требуют работы с отдельными битами.
Адрес сети: граница внутри октета
В задании EGE-10-0097 ↗ даны адрес 96.224.188.76 и маска 255.255.255.240. Требуется сумма октетов адреса сети.
Первые три октета маски равны 255, поэтому числа 96, 224 и 188 остаются. Последний октет маски равен 240_{10}=11110000_2: сохраняются первые четыре бита последнего октета, остальные обнуляются.
| Последний октет | Восемь битов |
|---|---|
| Адрес: 76 | \mathtt{0100}\mid\mathtt{1100} |
| Маска: 240 | \mathtt{1111}\mid\mathtt{0000} |
| Побитовое И: 64 | \mathtt{0100}\mid\mathtt{0000} |
Черта в таблице — граница сетевых и узловых битов, добавленная для объяснения. Слева сохранилось \mathtt{0100}, справа появились четыре нуля. Получено 01000000_2=64, поэтому адрес сети — 96.224.188.64. В ответе нужна сумма, а не сам адрес:
96+224+188+64=572.
Граница может проходить и раньше. В EGE-10-0070 ↗ для адреса 121.51.134.115 дана маска 255.248.0.0. Во втором октете 51_{10}=00110011_2 и 248_{10}=11111000_2; после И остаётся 00110000_2=48. Оба следующих октета обнуляются. Сеть — 121.48.0.0, сумма — 121+48=169.
Последний адрес компьютера
Широковещательный адрес получается, если сохранить сетевую часть, а во всех узловых битах поставить единицы. Это наибольший адрес подсети. В рассматриваемых условиях адрес сети и широковещательный адрес запрещено назначать компьютерам. Значит, последний адрес компьютера на единицу меньше широковещательного.
В EGE-13-0001 ↗ дан адрес 68.203.243.87 с маской 255.255.224.0. Требуется сумма октетов последнего адреса компьютера.
Первые два октета сохраняются. В третьем октете маска 224_{10}=11100000_2 оставляет первые три бита. Последний октет целиком относится к узловой части.
| Третий октет | Сетевые и узловые биты |
|---|---|
| Исходный: 243 | \mathtt{111}\mid\mathtt{10011} |
| Маска: 224 | \mathtt{111}\mid\mathtt{00000} |
| Адрес сети: 224 | \mathtt{111}\mid\mathtt{00000} |
| Широковещательный: 255 | \mathtt{111}\mid\mathtt{11111} |
В адресе сети последние пять битов третьего октета и все восемь битов четвёртого равны нулю: 68.203.224.0. Для широковещательного адреса все эти 13 битов становятся единицами: 68.203.255.255. Предыдущий адрес — 68.203.255.254. Он и является последним доступным компьютеру. Сумма октетов:
68+203+255+254=780.
Вариант ответа может быть другим. В EGE-13-0002 ↗ адрес 205.99.68.249 с маской 255.255.248.0 даёт последний адрес 205.99.71.254. Требуется убрать точки, поэтому ответ — 2059971254, без сложения чисел и без добавления нулей.
Количество адресов с условием на единицы
В EGE-13-0015 ↗ сеть задана адресом 122.159.136.144 и маской 255.255.255.248. Нужно посчитать IP-адреса, у которых число единиц в двоичной записи всего адреса не кратно 4.
Последний октет маски 11111000_2 оставляет три свободных бита. Каждый из них принимает два значения независимо от остальных, поэтому в подсети 2^3=8 адресов. В адресе 144_{10}=\mathtt{10010}\mid\mathtt{000}_2 свободные биты уже нулевые; это адрес сети. Они меняются от \mathtt{000} до \mathtt{111}, то есть последний октет принимает значения от 144 до 151 включительно.
Сначала считаются единицы неизменной части. В октетах 122, 159 и 136 их соответственно 5, 6 и 2. В неизменном начале \mathtt{10010} последнего октета ещё 2. Всего 5+6+2+2=15. К этому числу прибавляются единицы трёх свободных битов.
| Свободные биты | Всего единиц | Не кратно 4? |
|---|---|---|
| \mathtt{000} | 15 | Да |
| \mathtt{001} | 16 | Нет |
| \mathtt{010} | 16 | Нет |
| \mathtt{011} | 17 | Да |
| \mathtt{100} | 16 | Нет |
| \mathtt{101} | 17 | Да |
| \mathtt{110} | 17 | Да |
| \mathtt{111} | 18 | Да |
Подходят пять строк, ответ — 5. Здесь спрашивают обо всех IP-адресах подсети, а не об адресах, разрешённых компьютерам. Поэтому крайние адреса с окончаниями \mathtt{000} и \mathtt{111} тоже проверены и учтены.
Когда адресов много
Для больших подсетей удобен перебор в Python. В EGE-13-0010 ↗ заданы 172.16.168.0 и 255.255.248.0; число единиц должно быть не кратно 3. Маска оставляет 11 свободных битов: перебираются 2^{11}=2048 адресов.
from ipaddress import ip_network
net = ip_network('172.16.168.0/255.255.248.0',
strict=False)
count = 0
for address in net:
ones = bin(int(address)).count('1')
if ones % 3 != 0:
count += 1
print(count) # 1366
ip_network строит подсеть по адресу и маске. Параметр strict=False позволяет передать и адрес узла: его узловые биты будут обнулены при определении сети. Цикл for address in net включает оба крайних адреса. int(address) переводит весь адрес в одно целое число; bin получает его двоичную запись, а count('1') считает единицы. Начальные нули на это количество не влияют.
Оператор % даёт остаток от деления. Условие ones % 3 != 0 выбирает числа, не кратные 3. Если требуется кратность, используется == 0. Так, в EGE-13-0011 ↗ для сети 172.16.96.0/255.255.224.0 требуется кратность 3; с этими данными и сравнением получается 2730.
Для чётности есть короткая проверка. При хотя бы одном свободном бите адреса разбиваются на пары, различающиеся только этим битом. В каждой паре число единиц у одного адреса чётное, у другого нечётное. Поэтому ровно половина всех адресов имеет нечётное число единиц. В EGE-13-0012 ↗ свободных битов 11, ответ — 2^{11}/2=1024. Для кратности 3, 4 или 5 такого правила половины нет.
Возможные ловушки
- Обнулён последний октет целиком. В EGE-10-0097 ↗ четыре его бита относятся к сети. Замена 76 на 0 меняет и сетевую часть. Побитовое И с 240 даёт 64; адрес сети может оканчиваться не нулём.
- Широковещательный адрес назначен компьютеру. В EGE-13-0001 ↗ адрес
68.203.255.255запрещён условием. Для последнего компьютера нужен предыдущий,68.203.255.254. При этом число 255 внутри других октетов само по себе не делает адрес запрещённым. - Из подсчёта автоматически вычтены два адреса. В EGE-13-0015 ↗ оба крайних адреса удовлетворяют условию и входят в ответ 5. Вызов
net.hosts()исключит их и даст 3. Выбор между всеми адресами и адресами компьютеров определяется вопросом. - Единицы посчитаны только в меняющейся части. В EGE-13-0010 ↗ неизменная часть содержит 8 единиц. Проверка кратности только свободных битов сдвигает условие и меняет ответ. Проверяется сумма единиц обеих частей либо запись целого адреса.
- В ответ перенесён не тот результат. EGE-13-0001 ↗ требует сумму октетов, а EGE-13-0002 ↗ — адрес без точек. Эти действия выполняются только после нахождения нужного адреса; они не заменяют вычисление сети.