Задание 13: IP-адреса и маски подсети

Задание 13 (повышенный уровень): как из IP-адреса и маски выделить адрес сети и номер узла.

Маска подсети — это 32-битное число, в котором слева идут единицы (биты сети), а справа нули (биты узла). Адрес сети получается побитовым И между IP-адресом и маской.

Как устроен IP-адрес

IPv4-адрес — это 32 бита, записанные как четыре числа 0–255 через точку (например 192.168.200.143). Каждое из четырёх чисел занимает 8 бит (октет). Адрес логически делится на две части: адрес сети (общий для всех компьютеров подсети) и номер узла (уникальный внутри сети). Где проходит граница — задаёт маска.

Что делает маска

Маска подсети — тоже 32 бита: слева сплошные единицы, справа сплошные нули. Например 255.255.255.192 в двоичном виде — это 26 единиц и 6 нулей. Правило:

  • Биты-единицы маски отмечают часть, относящуюся к адресу сети.
  • Биты-нули маски отмечают часть, относящуюся к номеру узла.

Чтобы получить адрес сети, нужно выполнить побитовое И (AND) между IP-адресом и маской: там, где в маске 1, бит адреса сохраняется; где 0 — обнуляется.

Адрес сети: разбор примера

IP-адрес узла 192.168.200.143, маска 255.255.255.192. Найти адрес сети. Считать побитово руками — долго и рискованно; на КЕГЭ это решается мгновенно через оператор &:

def octets(s):
    return [int(x) for x in s.split(".")]

ip   = "192.168.200.143"
mask = "255.255.255.192"

# побитовое И по каждому октету
net = [a & m for a, m in zip(octets(ip), octets(mask))]
print("адрес сети:", ".".join(map(str, net)))

Вывод:

адрес сети: 192.168.200.128

Что произошло в последнем октете: 143 = 10001111, маска 192 = 11000000. Побитовое И оставляет только два старших бита: 10000000 = 128. Остальные октеты совпадают, потому что в маске там сплошные единицы (255).

Номер узла

Номер узла — это «оставшаяся» часть адреса, то есть биты, где маска равна нулю. Его получают побитовым И между IP и инвертированной маской:

def octets(s):
    return [int(x) for x in s.split(".")]

ip   = "192.168.200.143"
mask = "255.255.255.192"

# инвертированная маска: 255 - m по каждому октету
host = [a & (255 - m) for a, m in zip(octets(ip), octets(mask))]
print("номер узла (по октетам):", host)
print("номер узла (число):", host[-1])

Вывод:

номер узла (по октетам): [0, 0, 0, 15]
номер узла (число): 15

В последнем октете 143 = 10001111, инверсия маски = 00111111, их И = 00001111 = 15. То есть это узел номер 15 в своей подсети.

Сколько узлов в подсети

Число доступных узлов определяется количеством нулей в маске: если нулей k, то всего комбинаций 2k, но два адреса служебные (адрес самой сети — все нули, и широковещательный — все единицы), поэтому узлов 2k − 2.

mask = "255.255.255.192"
# считаем нули в двоичной записи маски
zeros = sum(bin(255 - m).count("1") for m in [int(x) for x in mask.split(".")])
ones  = 32 - zeros
print("единиц в маске:", ones, "-> запись /" + str(ones))
print("нулей (бит под узлы):", zeros)
print("узлов в подсети:", 2 ** zeros - 2)

Вывод:

единиц в маске: 26 -> запись /26
нулей (бит под узлы): 6
узлов в подсети: 62

Связь маски и «слэш-нотации»

Запись вида /26 означает «26 единиц в маске». Полезно помнить ключевые маски:

МаскаЕдиницНулейУзлов
255.255.255.024 (/24)8254
255.255.255.12825 (/25)7126
255.255.255.19226 (/26)662
255.255.255.22427 (/27)530
255.255.255.24028 (/28)414

Тип «найди маску по IP и адресу сети»

Иногда дают IP и адрес сети, а просят найти маску (или её последний октет). Метод: маска — это число, которое при побитовом И с IP даёт адрес сети. Переберём все 9 возможных значений старших единиц в октете и проверим:

ip_oct  = 143      # последний октет IP
net_oct = 128      # последний октет адреса сети
valid = []
for ones in range(0, 9):
    m = (256 - (1 << (8 - ones))) % 256 if ones < 8 else 255
    if (ip_oct & m) == net_oct:
        valid.append((ones, m))
print("подходящие (число единиц, значение октета маски):", valid)
print("наименьшая маска (минимум единиц):", min(valid))

Вывод:

подходящие (число единиц, значение октета маски): [(1, 128), (2, 192), (3, 224), (4, 240)]
наименьшая маска (минимум единиц): (1, 128)

Обратите внимание: подходящих масок несколько. Это закономерно — добавление лишних единиц слева не нарушает уже совпавшие старшие биты. Поэтому если просят наименьшую маску (минимум единиц, максимум узлов), берут вариант с наименьшим числом единиц — здесь 128 (/25 в последнем октете). Если просят наибольшую — наоборот, максимум единиц.

Деление сети на подсети

Ещё одна разновидность: «Сеть с маской /24 нужно разбить на подсети так, чтобы в каждой было не менее 50 узлов. Какую маску взять и сколько подсетей получится?» Логика: под 50 узлов нужно столько бит, чтобы 2k − 2 ≥ 50; оставшиеся биты идут под номера подсетей. Переберём:

# исходная маска /24 -> 8 бит на узлы; нужно >= 50 узлов в подсети
need = 50
# сколько бит под узлы минимально нужно
host_bits = 0
while 2 ** host_bits - 2 < need:
    host_bits += 1
print("бит под узлы:", host_bits, "-> узлов:", 2 ** host_bits - 2)

# из 8 «свободных» бит /24 под узлы ушло host_bits, остальное — под подсети
subnet_bits = 8 - host_bits
new_mask = 24 + subnet_bits
print("новая маска: /" + str(new_mask))
print("число подсетей:", 2 ** subnet_bits)

Вывод:

бит под узлы: 6 -> узлов: 62
новая маска: /26
число подсетей: 4

Под 50 узлов берём 6 бит (62 ≥ 50, а 5 бит дали бы только 30). Значит из восьми «хвостовых» бит /24 два освобождаются под номера подсетей: 22 = 4 подсети с маской /26. Это та же арифметика степеней двойки, что и во всём разделе кодирования.

Типичные ловушки

  • «Минус 2». Из 2k вычитают 2 служебных адреса. Иногда в задании спрашивают «сколько всего адресов» — тогда без минуса.
  • Адрес сети ≠ номер узла. Адрес сети — И с маской; номер узла — И с инвертированной маской.
  • Маска идёт единицами слева. Значение октета маски всегда из ряда 0, 128, 192, 224, 240, 248, 252, 254, 255 — других не бывает.
  • Больше единиц в маске = меньше узлов. «Наибольшее количество узлов» означает наименьшее число единиц в маске.

Итог

  • Адрес сети = IP & маска; номер узла = IP & (инвертированная маска).
  • Число узлов = 2(нулей в маске) − 2.
  • Значения октетов маски — только из ряда 0, 128, 192, 224, 240, 248, 252, 254, 255.
Проверьте себя
1. Как получить адрес сети из IP-адреса и маски?
AПобитовое ИЛИ IP и маски
BПобитовое И IP и маски
CСложить IP и маску
DПобитовое И IP и инвертированной маски
2. В маске 255.255.255.224 сколько бит отведено под номер узла?
A3
B5
C27
D8
3. Сколько узлов можно адресовать в сети с маской, где под узлы отведено 6 бит?
A64
B62
C6
D32
Поддержать проект