Веду на сто
Учебная статья

Задание №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 ↗ — адрес без точек. Эти действия выполняются только после нахождения нужного адреса; они не заменяют вычисление сети.