Задание 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.0 | 24 (/24) | 8 | 254 |
| 255.255.255.128 | 25 (/25) | 7 | 126 |
| 255.255.255.192 | 26 (/26) | 6 | 62 |
| 255.255.255.224 | 27 (/27) | 5 | 30 |
| 255.255.255.240 | 28 (/28) | 4 | 14 |
Тип «найди маску по 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.