Задание 10
Маска подсети
Как по IP-адресу и маске найти адрес сети, её края и число адресов — и как найти маску, если её не дали.
6 подтем · 54 задачи + 7 дополнительных · базовый · ≈ 3 мин
Подтема 1 из 6
IP-адрес и маска
Что такое IP-адрес и маска, как записать их битами и какие маски вообще бывают.
Как устроена тема
В задании 10 дан IP-адрес компьютера и маска сети. Нужно понять, какие адреса входят в эту сеть, — найти её края, посчитать адреса или, наоборот, восстановить маску. Вот задача, которую мы будем решать всю тему:
«Сеть задана IP-адресом одного из входящих в неё узлов 172.20.77.140 и маской сети 255.255.252.0. Найди наибольший IP-адрес этой сети, который может быть назначен компьютеру. В ответе запиши сумму значений его октетов.»
Адрес и маску записывают битами: маска делит адрес на часть сети и часть узла, и дальше всё видно по битам. Вручную обычно хватает одного октета, а программа делает то же модулем ipaddress. Сначала разберём, что сказано в условии:
| В условии | Что это значит |
|---|---|
| узел 172.20.77.140 | адрес одного компьютера сети — четыре числа по 8 битов |
| маска 255.255.252.0 | граница: слева от неё биты сети, справа — номер компьютера |
| наибольший адрес, который может быть назначен компьютеру | последний адрес сети не годится — нужен предыдущий |
| сумма значений октетов | сложить четыре числа адреса |
Тема состоит из шести подтем — у каждой своя страница. Идём по ним по порядку:
- IP-адрес и маска — ты сейчас здесь.
- Адрес сети и границы сети — края сети и ответ задачи темы: 525.
- Количество адресов и номер узла — сколько адресов в сети и какой номер у компьютера.
- Неизвестная маска — как найти маску, если её не дали.
- Адреса с условием на двоичную запись — сколько адресов с нужным числом единиц.
- Маска по условию и сочетания — дополнительный урок для редких задач.
Почти везде задачу можно решить и вручную, и программой — выбирай вкладку «Вручную» или «Python». На экзамене подойдёт любой способ, а второй пригодится для проверки.
32 бита
Что на самом деле записано в 172.20.77.140?
IP-адрес — 32 бита: четыре октета по восемь битов, каждый октет записан десятичным числом от 0 до 255. Бит — одна двоичная цифра, 0 или 1; октет (байт) — восемь битов. Точки только разделяют октеты.
Позиции октета справа налево стоят 1, 2, 4, 8, 16, 32, 64, 128. Единица в позиции добавляет её значение к числу:
| Позиция | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|---|---|
| Бит | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
10001100₂ = 128 + 8 + 4 = 140. Октет всегда записывают ровно восемью битами: 20 = 10100₂, но внутри адреса это 00010100 — нули слева сохраняют позиции.
Значения позиций проверяют от большего к меньшему: в 140 помещается 128 — пишем 1, остаётся 12; 64, 32 и 16 не помещаются — три нуля; 8 помещается — 1, остаётся 4; 4 помещается — 1, остаётся 0; дальше нули. Получаем 10001100.
| Октет | Биты |
|---|---|
| 172 | 10101100 |
| 20 | 00010100 |
| 77 | 01001101 |
| 140 | 10001100 |
Тот же перебор позиций делают : частное — очередной бит, остаток — что осталось. Пройди по шагам:
n = 140bits = ''for w in [128, 64, 32, 16, 8, 4, 2, 1]: bits += str(n // w) n = n % wprint(bits)Весь адрес сразу даёт стандартный модуль : ip_address превращает строку в адрес, запись f'{address:b}' () — в 32 бита с нулями слева, а int(address) — в одно целое число:
from ipaddress import ip_addressaddress = ip_address('172.20.77.140')print(f'{address:b}')print(int(address))Тонкости:255 и 256, bin
Наибольший октет — 11111111₂ = 255, а значений у октета 256: от 0 до 255, 2⁸ вариантов. Не путай наибольшее значение с количеством.
Функция возвращает '0b10100' — с приставкой и без нулей слева. Считать по ней нули адреса нельзя: их часть потеряна.
Маска
Маска — тоже 32 бита: сначала единицы, потом нули. Единицы отмечают часть сети, нули — часть узла. Часть сети одинакова у всех адресов сети, часть узла различает компьютеры внутри неё.
В маске 255.255.252.0 два октета 255 — 16 единиц, 252 = 11111100 — ещё 6 единиц и 2 нуля, в последнем октете 8 нулей. Всего 22 единицы: первые 22 бита адреса — сеть, последние 10 — узел. Граница проходит внутри третьего октета, а не по точке:
Маску коротко записывают числом единиц: 255.255.252.0 — это /22. Обозначим p — длину префикса (число единиц маски), h — число битов части узла: p + h = 32, у /22 h = 10.
Единица маски не требует единицы в адресе: она говорит только, что этот бит — сетевой и одинаков у всех адресов сети. Сам бит может быть и нулём, и единицей — у 77 сетевые биты третьего октета 010011.
Допустимые маски
У маски единицы идут подряд слева, поэтому октет маски бывает только девяти видов, и смешанный октет в маске один. Перед ним — октеты 255, после него — октеты 0.
| Единиц | Биты | Октет |
|---|---|---|
| 0 | 00000000 | 0 |
| 1 | 10000000 | 128 |
| 2 | 11000000 | 192 |
| 3 | 11100000 | 224 |
| 4 | 11110000 | 240 |
| 5 | 11111000 | 248 |
| 6 | 11111100 | 252 |
| 7 | 11111110 | 254 |
| 8 | 11111111 | 255 |
Таблицу легко восстановить: 128, 128 + 64 = 192, 192 + 32 = 224 и так далее. Число 250 = 11111010 в маске невозможно — после нуля снова единица. Маска 255.0.255.0 тоже невозможна.
Маску /20 строят слева: 16 единиц — два октета 255, оставшиеся 4 единицы — 11110000 = 240, последний октет 0. Получаем 255.255.240.0. Обратно: 255.255.252.0 — 8 + 8 + 6 = 22 единицы.
ip_network строит сеть по записи «адрес/маска», свойство netmask — её маска четырьмя октетами. Адрес 0.0.0.0 здесь только заготовка:
from ipaddress import ip_networkfor p in [20, 22, 24, 26]: print(p, ip_network(f'0.0.0.0/{p}').netmask)Допустимость маски проверяют по 32 битам: «после нуля снова единица» — это :
from ipaddress import ip_addressfor mask in ['255.255.252.0', '255.255.250.0']: bits = f'{ip_address(mask):b}' print(mask, '01' not in bits)Итого
- IP-адрес32 бита, четыре октета от 0 до 255
- Октетровно 8 битов, нули слева сохраняют позиции
- Маскаединицы — сеть, нули — узел; сначала единицы
- /pp единиц маски, h = 32 − p битов узла
- Python
f'{address:b}',ip_network(…).netmask
Проверьте себя
Ответь сначала сам, потом открой ответ.
ОтветСкрыть ответ
00010100: 20 = 16 + 4, нули слева сохраняют позиции.11001000 в число.ОтветСкрыть ответ
ОтветСкрыть ответ
255.255.240.0: 16 единиц — два октета 255, ещё 4 единицы — 11110000 = 240.ОтветСкрыть ответ
11111010, после нуля снова единица.255.255.255.224?ОтветСкрыть ответ
Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Октет в двоичной записи
Переведи число 150 в восьмибитную двоичную запись.
Введите восемь битов.
Подсказка
Позиции октета — 128, 64, 32, 16, 8, 4, 2, 1; всего ровно восемь битов.
Решение
Значения позиций проверяем от большего к меньшему: 150 = 128 + 16 + 4 + 2, поэтому единицы стоят в позициях 128, 16, 4 и 2 — 10010110.
Решение программой
print(f'{150:08b}')Ответ: 10010110
Единицы октета 37
Сколько единиц в двоичной записи октета 37?
Введите число.
Подсказка
Разложи 37 по позициям 128, 64, …, 1.
Решение
37 = 32 + 4 + 1, восемью битами — 00100101: в записи три единицы.
Решение программой
print(f'{37:08b}'.count('1'))Ответ: 3
Единицы адреса 192.168.10.173
Сколько единиц в полной двоичной записи адреса 192.168.10.173?
Введите число.
Подсказка
Запиши каждый октет восемью битами и сложи единицы всех четырёх.
Решение
Октеты — 11000000, 10101000, 00001010 и 10101101: в них 2, 3, 2 и 5 единиц, всего 12.
Решение программой
octets = '192.168.10.173'.split('.')bits = ''.join(f'{int(x):08b}' for x in octets)print(bits.count('1'))Ответ: 12
Биты части узла
Маска равна 255.255.254.0. Сколько битов в части узла?
Введите число.
Подсказка
Сосчитай единицы маски; остальные биты из 32 — часть узла.
Решение
254 = 11111110, поэтому в маске 8 + 8 + 7 = 23 единицы. Частью узла остаются 32 − 23 = 9 битов.
Решение программой
from ipaddress import ip_address, ip_network p = ip_network('0.0.0.0/255.255.254.0').prefixlenprint(32 - p)Ответ: 9
Маска /27
Запиши маску /27 в виде четырёх десятичных чисел.
Введите маску: четыре числа через точку.
Подсказка
Полные октеты — 255, остаток единиц — в одном октете.
Решение
Первые 24 единицы занимают три полных октета 255, ещё три единицы дают 11100000 = 224. Маска — 255.255.255.224.
Решение программой
from ipaddress import ip_address, ip_network print(ip_network('0.0.0.0/27').netmask)Ответ: 255.255.255.224
Маска с 29 единицами
Маска имеет вид 255.255.255.X и содержит 29 единиц. Найди X.
Введите число.
Подсказка
Сколько единиц остаётся на последний октет?
Решение
Первые три октета 255 дают 24 единицы, в последнем октете остаётся 29 − 24 = 5 единиц: 11111000 = 248.
Решение программой
from ipaddress import ip_address, ip_network print(ip_network('0.0.0.0/29').netmask.packed[3])Ответ: 248
Маски вида 255.255.X.0
Сколько существует допустимых масок вида 255.255.X.0?
Введите число.
Подсказка
В октете маски единицы идут подряд слева.
Решение
Октет X может быть любым из девяти допустимых значений — 0, 128, 192, 224, 240, 248, 252, 254, 255: перед ним идут единицы, после — нулевой октет, и непрерывность не нарушается.
Решение программой
print(sum(1 for x in range(256) if '01' not in f'{x:08b}'))Ответ: 9