Задание 13: IP-адресация и маска подсети
- Тема: работа с IP-адресами, масками подсети, адресами сети и широковещательными адресами.
- Ответ: целое число или слово.
- Балл: 1. Время: 3-4 мин. Сложность: повышенная (средний процент выполнения: 44%).
Задания: N13.IP-адресация и маска подсети
Основные понятия
IP-адрес
32-битное число (IPv4), записывается четырьмя ,байтами(октетами) от 0 до 255, разделёнными точками.
Пример: 192.168.1.3 11000000.10101000.00000001.00000011
IP-адрес состоит из двух частей:
- Адрес сети - общая часть для всех устройств в сети (биты, где в маске стоят 1).
- Адрес узла (хоста) - часть, идентифицирующая конкретное устройство (биты, где в маске стоят 0).
Маска подсети
32-битное число, определяющее, какая часть IP-адреса - адрес сети, а какая - адрес узла.
Правило: в маске сначала идут единицы (сетевая часть), затем нули (хостовая часть). Нули и единицы не перемежаются.
Допустимые значения каждого октета маски:
0, 128, 192, 224, 240, 248, 252, 254, 255
Примеры допустимых масок:
| Маска | Двоичная запись | Префикс |
|---|---|---|
| 255.0.0.0 | 11111111.00000000.00000000.00000000 | /8 |
| 255.255.0.0 | 11111111.11111111.00000000.00000000 | /16 |
| 255.255.255.0 | 11111111.11111111.11111111.00000000 | /24 |
| 255.255.248.0 | 11111111.11111111.11111000.00000000 | /21 |
| 255.255.255.128 | 11111111.11111111.11111111.10000000 | /25 |
CIDR-нотация: 192.168.0.0/24 - запись, где /24 означает количество единиц в маске (префикс).
Адрес сети
Получается побитовой операцией AND (конъюнкция) между IP-адресом и маской. В адресе сети все биты хостовой части равны 0.
Пример:
IP-адрес: 135.213.234.10 → 10000111.11010101.11101010.00001010
Маска: 255.255.248.0 → 11111111.11111111.11111000.00000000
AND
Адрес сети: 135.213.232.0 → 10000111.11010101.11101000.00000000
Широковещательный адрес
Адрес, где все биты хостовой части равны 1. Используется для отправки данных всем устройствам сети. Не назначается конкретным устройствам.
Получается операцией OR между адресом сети и инвертированной маской.
Пример (продолжение):
Адрес сети: 135.213.232.0 → 10000111.11010101.11101000.00000000
Инверсия маски: 0.0.7.255 → 00000000.00000000.00000111.11111111
OR
Широковещательный: 135.213.239.255 → 10000111.11010101.11101111.11111111
Пример. Зачем нужна маска?
Пусть есть некий район Эчпочмаковский с номером 192, в этом районе есть улица Казанская с номером 168 на которой стоят 3 дома и в каждой по 3 квартиры.
У нас есть IP-адрес 192(район).168(улица).1(дом).5(квартира) из 5 кв 1 дома, и чтобы узнать адрес сети всей улицы, нужно сделать побитовую коньюкцию с маской подсети, где на месте номера района и номера улицы будут 1, а на месте где дом и квартира 0
Получается IP-адрес: 192.168.1.5 или 11000000.10101000.00000001.00000101
Маска подсети: 111111111.11111111.00000000.00000000 или 255.255.0.0
Тогда адрес сети улицы будет: 11000000.10101000.00000000.00000000 или 192.168.0.0
Диапазон адресов хостов
Все адреса между адресом сети и широковещательным (не включая их).
Правило: в любой сети всегда зарезервированы 2 адреса, которые нельзя назначить устройствам:
- первый адрес диапазона - адрес сети (все биты хостовой части = 0);
- последний адрес диапазона - широковещательный адрес (все биты хостовой части = 1).
Количество адресов в сети: 2^(32 - префикс)
Количество хостов: 2^(32 - префикс) - 2 (вычитаем эти 2 зарезервированных адреса)
Пример: маска /21 (255.255.248.0):
- Количество адресов:
2^(32-21) = 2^11 = 2048 - Количество хостов:
2048 - 2 = 2046
Алгоритм решения
- Перевести IP-адрес и маску в двоичный вид (по октетам).
- Найти адрес сети:
IP AND маска. - Найти широковещательный адрес:
адрес_сети OR (инверсия маски). - Определить диапазон адресов хостов.
- Ответить на конкретный вопрос задачи.
- Перевести результат обратно в десятичный вид.
Типы заданий
| Тип | Что дано | Что найти |
|---|---|---|
| 1 | IP + маска | адрес сети |
| 2 | IP + адрес сети | наименьший возможный байт маски |
| 3 | маска | количество возможных адресов хостов |
| 4 | IP + маска | количество адресов по условию в диапазоне |
| 5 | IP + маска | принадлежит ли адрес данной сети |
| 6 | IP + маска | широковещательный адрес |
| 7 | несколько IP + маска | сколько устройств в одной подсети |
Полезные команды Python
Перевод систем счисления
# Десятичное - двоичное (строка без '0b')
bin(83) # '0b1010011'
f"{83:08b}" # '01010011' <- удобнее, с ведущими нулями
# Двоичное - десятичное
int("01010011", 2) # 83
Побитовые операции
| A | B | A AND B | A OR B |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 |
AND даёт 1 только если оба бита = 1 (используется для нахождения адреса сети). OR даёт 1 если хотя бы один бит = 1 (используется для нахождения широковещательного адреса).
a = 0b10111001 # 185
b = 0b11111000 # 248
a & b # AND (конъюнкция) - нахождение адреса сети
a | b # OR (дизъюнкция) - нахождение широковещательного адреса
~a # NOT (инверсия) - инверсия маски (осторожно: даёт отрицательное число!)
a ^ b # XOR
# Инверсия маски безопасно (для 8-битного октета):
~b & 0xFF # 0b00000111 = 7
# Сдвиги
a >> 1 # сдвиг вправо (деление на 2)
a << 1 # сдвиг влево (умножение на 2)
Работа с октетами IP-адреса
ip_str = "185.49.83.72"
octets = list(map(int, ip_str.split("."))) # [185, 49, 83, 72]
# AND двух адресов октет за октетом
mask = [255, 255, 248, 0]
net = [a & b for a, b in zip(octets, mask)] # [185, 49, 80, 0]
print(".".join(map(str, net))) # '185.49.80.0'
# Двоичное представление каждого октета
for o in octets:
print(f"{o:08b}")
Модуль ipaddress
import ipaddress
net = ipaddress.ip_network("135.213.232.0/21", strict=False)
net.network_address # IPv4Address('135.213.232.0')
net.broadcast_address # IPv4Address('135.213.239.255')
net.netmask # IPv4Address('255.255.248.0')
net.prefixlen # 21
net.num_addresses # 2048
# Кол-во хостов (без адреса сети и широковещательного)
len(list(net.hosts())) # 2046
# Принадлежит ли IP сети
ip = ipaddress.ip_address("135.213.234.10")
ip in net # True
# Создать сеть из IP + маска
net2 = ipaddress.ip_network(f"185.49.83.72/255.255.248.0", strict=False)
# Перебор адресов в диапазоне (для типа 4)
for host in net.hosts():
last = int(host) & 0xFF # правый байт
binary = f"{last:08b}"
if "000" not in binary:
print(host)
Разбор примера: нахождение минимального байта маски
Задача: для узла с IP-адресом 185.49.83.72 адрес сети равен 185.49.80.0. Чему равен наименьший возможный третий байт маски?
Решение:
Переводим третьи байты в двоичный вид:
IP-адрес (3-й байт): 83 → 01010011
Адрес сети (3-й байт): 80 → 01010000
Биты совпадают в позициях 1-6 (слева), различаются в 7-8 позициях. Но там где 00, мы можем поставить 0 или 1, так как минимально езначение то ставим 0.
Маска должна иметь единицы там, где биты совпадают, и нули там, где различаются.
Минимальная маска - та, где как можно больше нулей.
Первые 4 бит совпадают, значит маска минимум 11110000 = 240.
Ответ: 240
Разбор примера: нахождение максимального байта маски по числу хостов
Задача: IP-адрес сети 176.112.100.128, в ней может быть 14 компьютеров. Чему равен максимально возможный крайний правый байт маски сети?
Шаг 1. Определяем нужное количество адресов
14 компьютеров + 2 зарезервированных = 16 адресов.
Шаг 2. Определяем количество бит под хостовую часть
Нужно 2^n >= 16 → 2^4 = 16 → n = 4 бита под хосты.
Шаг 3. Составляем последний байт маски
В байте 8 бит. 4 бита - под хосты (нули в маске), оставшиеся 4 - под сеть (единицы):
11110000
Шаг 4. Переводим в десятичное
print(int("11110000",2))
Максимальный байт маски - это когда единиц как можно больше (нулей как можно меньше), то есть под хосты отведено ровно столько бит, сколько необходимо. Меньше нулей = больше значение байта маски.
Ответ: 240
Разбор примера: подсчёт адресов по условию на количество единиц
Задача: сеть задана IP-адресом 122.159.136.144 и маской 255.255.255.248. Сколько в этой сети IP-адресов, для которых количество единиц в двоичной записи не кратно 4?
Шаг 1. Определяем диапазон адресов сети
Последний байт маски 248 = 11111000 - три нуля, значит 2^3 = 8 адресов в сети.
Правило:
шаг сети = 256 - последний байт маски = 256 - 248 = 8Сети начинаются с кратных 8 чисел: ...136, 144, 152... Диапазон:144 - 151(144 + 8 - 1 = 151)
Все IP-адреса сети:
| IP-адрес | Последний байт |
|---|---|
| 122.159.136.144 | 144 |
| 122.159.136.145 | 145 |
| ... | ... |
| 122.159.136.151 | 151 |
Шаг 2. Считаем единицы в первых трёх байтах (они одинаковы для всех адресов)
122 → 01111010 → 5 единиц
159 → 10011111 → 6 единиц
136 → 10001000 → 2 единицы
Итого: 13
Шаг 3. Таблица: единицы в последнем байте + итог по всему адресу
| Последний байт | Двоично | Единиц | Итого (13 + N) | Кратно 4? |
|---|---|---|---|---|
| 144 | 10010000 |
2 | 15 | нет |
| 145 | 10010001 |
3 | 16 | да |
| 146 | 10010010 |
3 | 16 | да |
| 147 | 10010011 |
4 | 17 | нет |
| 148 | 10010100 |
3 | 16 | да |
| 149 | 10010101 |
4 | 17 | нет |
| 150 | 10010110 |
4 | 17 | нет |
| 151 | 10010111 |
5 | 18 | нет |
Шаг 4. Считаем подходящие адреса
Не кратно 4: 144, 147, 149, 150, 151 - итого 5.
Решение на Python:
bits = bin(122).count("1") + bin(159).count("1") + bin(136).count("1") # = 13
otv = 0
for x in range(144, 152): # 8 адресов: 144..151
a = bits + bin(x).count("1")
if a % 4 != 0:
otv += 1
print(otv) # 5
Ответ: 5
Полезные формулы
| Что найти | Формула |
|---|---|
| Адрес сети | IP AND маска |
| Широковещательный адрес | адрес_сети OR (NOT маска) |
| Количество адресов в сети | 2^(32 - префикс) |
| Количество хостов | 2^(32 - префикс) - 2 |
| Префикс из маски | посчитать единицы в двоичной записи маски |
Разбор примера: нахождение максимального адреса компьютера в сети
Задача: сеть задана IP-адресом узла 98.81.154.195 и маской 255.252.0.0. Найдите наибольший IP-адрес, который может быть назначен компьютеру. Ответ запишите без разделителей.
Шаг 1. Переводим маску в двоичный вид
255 → 11111111
252 → 11111100
0 → 00000000
0 → 00000000
Маска: 11111111.11111100.00000000.00000000
|-- 14 бит сети --|---- 18 бит хостов ----|
Шаг 2. Находим адрес сети (IP AND маска)
Первый, третий и четвёртый байты маски очевидны (255 и 0). Считаем только второй:
IP: 81 → 01010001
Маска 252 → 11111100
AND
01010000 = 80
Адрес сети: 98.80.0.0
Шаг 3. Находим широковещательный адрес
Широковещательный адрес - все биты хостовой части заменяем на 1.
Во втором байте последние 2 бита - хостовые:
Сетевая часть байта: 010100 → ставим хостовые биты в 1
010100|11 = 01010011 = 83
Третий и четвёртый байты полностью хостовые - заменяем на 255:
Широковещательный адрес: 98.83.255.255
Шаг 4. Максимальный адрес компьютера
Максимальный адрес хоста = широковещательный адрес - 1
98.83.255.255 - 1 = 98.83.255.254
Решение на Python:
import ipaddress
net = ipaddress.ip_network("98.81.154.195/255.252.0.0", strict=False)
max_host = net.broadcast_address - 1
# Ответ без разделителей
print("".join(str(max_host).split("."))) # 9883255254
Ответ: 9883255254
Разбор примера: нахождение максимального адреса компьютера (2)
Задача: сеть задана IP-адресом узла 205.99.68.249 и маской 255.255.248.0. Найдите наибольший IP-адрес, который может быть назначен компьютеру. Ответ запишите без разделителей.
Шаг 1. Определяем шаг подсети
Третий байт маски 248 = 11111000 - три нуля, четвёртый байт маски 0 = 00000000 - восемь нулей.
шаг по третьему байту = 256 - 248 = 8
Сети начинаются: ...56, 64, 72... - берём ближайшее кратное 8, не превышающее 68.
Шаг 2. Находим адрес сети
Первый, второй, четвёртый байты очевидны (255, 255 и 0). Считаем только третий:
IP: 68 → 01000100
Маска 248 → 11111000
AND
01000000 = 64
Адрес сети: 205.99.64.0
Шаг 3. Находим широковещательный адрес
Хостовые части - последние 3 бита третьего байта и весь четвёртый байт - заменяем на 1:
Третий байт: 64 + 7 = 71 (01000000 | 00000111 = 01000111)
Четвёртый байт: 255
Широковещательный адрес: 205.99.71.255
Шаг 4. Максимальный адрес компьютера
205.99.71.255 - 1 = 205.99.71.254
Решение на Python:
ip = [205, 99, 68, 249]
mask = [255, 255, 248, 0]
net = [a & b for a, b in zip(ip, mask)]
broadcast = [n | (255 - m) for n, m in zip(net, mask)]
max_host = broadcast[:]
max_host[3] -= 1
print("".join(str(x) for x in max_host)) # 2059971254
Ответ: 2059971254
Материалы будут дополняться.