В этой статье продолжим разбирать задания № 13 из ЕГЭ по информатике. Если в первой части мы решали задачи аналитически, то теперь перейдём к программному подходу и научимся использовать модуль ipaddress на Python. Это позволяет быстрее проверять гипотезы, перебирать варианты и решать даже сложные задачи без громоздких вычислений вручную.
Термины, которые будем использовать: маска подсети, адрес сети, IP-адрес, узел (хост), широковещательный адрес, бит сети, бит узла, октет, поразрядная конъюнкция.
Основные методы из библиотеки ipaddress
Для решения задач нам понадобится несколько базовых функций и свойств.
1. ip_address() — создание объекта IP-адреса
from ipaddress import ip_address
addr = ip_address(‘192.168.1.1’)
print(addr) # 192.168.1.1
print(int(addr)) # 3232235777 (числовое представление)2. ip_network() — создание объекта сети
Это главная функция для решения задач. Она принимает строку с IP и маской (в формате 4 октетов или десятичном) и возвращает объект сети.
from ipaddress import ip_network
# Способ 1:
net = ip_network(‘192.168.1.0/24’, False)
# Способ 2: IP и маска через слеш
net = ip_network(‘192.168.1.10/255.255.255.0’, False)
# Способ 3: IP и маска через f-строку
ip = ‘192.168.1.10’
mask = ‘255.255.255.0’
net = ip_network(f'{ip}/{mask}’, False)
Параметр False очень важен. Он позволяет создать сеть, даже если передан не адрес сети, а адрес узла (как часто бывает в условии задачи).
3. Основные атрибуты объекта сети
| Атрибут | Что возвращает | Пример для сети 192.168.1.0/24 |
|---|---|---|
| net.network_address | Адрес сети | 192.168.1.0 |
| net.netmask | Маска подсети | 255.255.255.0 |
| net.num_addresses | Общее количество адресов в сети (включая сетевой и широковещательный) | 256 |
4. Перебор узлов в сети
from ipaddress import ip_network
net = ip_network(‘192.168.1.0/29’, False)
for host in net:
print(host) # будут выведены в том числе сетевой и широковещательный адреса
5. Метод hosts() — перебор адресов узлов
from ipaddress import ip_network
net = ip_network(‘192.168.1.0/29’, False)
for host in net.hosts():
print(host)
# Вывод: 192.168.1.1, 192.168.1.2, …, 192.168.1.6
hosts() возвращает только адреса узлов (исключая адрес сети и широковещательный). Это удобно, когда нужно найти, например, минимальный или максимальный адрес в сети, который можно назначить компьютеру (сетевой и широковещательный назначать нельзя).
Важное исключение: для масок /31 и /32 поведение меняется — они возвращают все адреса, включая сетевой.
6. Доступ к адресам по индексу
Объект IPv4Network ведёт себя как список, хранящий адреса: можно обращаться к адресам по индексу.
python
from ipaddress import ip_network
net = ip_network(‘192.168.1.0/24’, False)
print(net[0]) # адрес сети — 192.168.1.0
print(net[1]) # первый доступный узел — 192.168.1.1
print(net[-1]) # широковещательный адрес — 192.168.1.255
print(net[-2]) # последний доступный узел — 192.168.1.254
Чтобы найти минимальный или максимальный адрес в сети, не нужно ничего вычислять вручную.
7. Перебор масок
from ipaddress import ip_network
for mask in range(33):
net = ip_network(f’192.168.1.0/{mask}’, False)
print(net)
Когда не дана маска и необходимо найти такую, при которой выполняется определённое условие, можно перебирать количество единиц в маске от 0 до 32 включительно и далее в цикле анализировать получившуюся сеть.
Разбор типовых задач
Задача 1
В терминологии сетей TCP/IP маской сети называется двоичное число, определяющее, какая часть IP-адреса узла сети относится к адресу сети, а какая — к адресу самого узла в этой сети. При этом в маске сначала (в старших разрядах) стоят единицы, а затем с некоторого места — нули. Обычно маска записывается по тем же правилам, что и IP-адрес, — в виде четырёх байтов, причём каждый байт записывается в виде десятичного числа. Адрес сети получается в результате применения поразрядной конъюнкции к заданному IP-адресу узла и маске.
Например, если IP-адрес узла равен 231.32.255.131, а маска равна 255.255.240.0, то адрес сети равен 231.32.240.0.
Для узла с IP-адресом 98.162.75.91 адрес сети равен 98.162.75.64. Чему равно наименьшее количество возможных адресов в этой сети?
from ipaddress import ip_network
for mask in range(32):
net = ip_network(f»98.162.75.91/{mask}», False)
if str(net.network_address) == «98.162.75.64»:
print(net.num_addresses)
Ответ: 32.
Задача 2
В терминологии сетей TCP/IP маской сети называют двоичное число, которое показывает, какая часть IP-адреса узла сети относится к адресу сети, а какая — к адресу узла в этой сети. Адрес сети получается в результате применения поразрядной конъюнкции к заданному адресу узла и маске сети.
Узлы с IP-адресами 193.45.192.104 и 193.45.206.210 находятся в разных сетях. Укажите наименьшее возможное значение третьего слева байта маски этой сети. Ответ запишите в виде десятичного числа.
from ipaddress import ip_network
for mask in range(33):
net1 = ip_network(f»193.45.192.104/{mask}», False)
net2 = ip_network(f»193.45.206.210/{mask}», False)
# узлы находятся в разных адресах
if net1 != net2:
# выводим первую подходящую маску (она одинаковая для обеих сетей)
print(str(net1.netmask).split(«.»)[2])
break
Ответ: 248.
Задача 3
В терминологии сетей TCP/IP маской сети называется двоичное число, определяющее, какая часть IP-адреса узла сети относится к адресу сети, а какая — к адресу самого узла в этой сети. Адрес сети получается в результате применения поразрядной конъюнкции к заданному адресу узла и маске сети.
Сеть задана IP-адресом 242.67.112.134 и маской сети 255.255.255.192. Сколько в этой сети IP-адресов, для которых в двоичной записи IP-адреса суммарное количество единиц в левых двух байтах не менее суммарного количества единиц в правых двух байтах?
В ответе укажите только число.
from ipaddress import ip_network
k = 0
for ad in ip_network(«242.67.112.134/255.255.255.192», False):
binAd = bin(int(ad))[2:].zfill(32)
if binAd[:16].count(«1») >= binAd[16:].count(«1»):
k += 1
print(k)
Ответ: 57.
Задача 4
В терминологии сетей TCP/IP маской сети называется двоичное число, определяющее, какая часть IP-адреса узла сети относится к адресу сети, а какая — к адресу самого узла в этой сети. Адрес сети получается в результате применения поразрядной конъюнкции к заданному адресу узла и маске сети.
Сеть задана IP-адресом 255.112.1.136 и маской сети 255.255.Х.0, где Х — число, заданное в диапазоне от 0 до 255. Определите минимальное значение Х, для которого для всех IP-адресов этой сети в двоичной записи IP-адреса суммарное количество единиц в левых двух байтах не менее суммарного количества единиц в правых двух байтах. В ответе укажите только число.
from ipaddress import ip_network
octets = [int(«1» * i + «0» * (8 — i), 2) for i in range(8)]
for x in octets:
mask = f»255.255.{x}.0″
for ad in ip_network(f»255.112.1.136/{mask}», False):
binAd = bin(int(ad))[2:].zfill(32)
if binAd[:16].count(«1») < binAd[16:].count(«1»):
break
else:
print(x)
break
Ответ: 248.
Задача 5
В терминологии сетей TCP/IP маской сети называется двоичное число, определяющее, какая часть IP-адреса узла сети относится к адресу сети, а какая — к адресу самого узла в этой сети. При этом в маске сначала (в старших разрядах) стоят единицы, а затем с некоторого места — нули. Адрес сети получается в результате применения поразрядной конъюнкции к заданному IP-адресу узла и маске.
Например, если IP-адрес узла равен 231.32.255.131, а маска равна 255.255.240.0, то адрес сети равен 231.32.240.0.
Узел с IP-адресом 121.96.174.205 принадлежит сети, в которой 10 IP-адресов, двоичная запись которых содержит ровно 12 единиц. Сколько единиц содержится в двоичной записи маски этой сети?
from ipaddress import ip_network
for mask in range(32, -1, -1):
net = ip_network(f»121.96.174.205/{mask}», False)
k = 0
for ad in net:
if bin(int(ad))[2:].zfill(32).count(«1») == 12:
k += 1
if k == 10:
print(mask)
break
Ответ: 22.
Заключение
Модуль ipaddress значительно упрощает решение задач № 13. Вместо ручных вычислений можно перебирать варианты, проверять условия и быстро находить ответ.
Такой подход особенно полезен на этапе подготовки: он помогает лучше понять структуру задач и проверить свои решения. Однако на экзамене важно уметь решать задания и без кода, поэтому оптимальная стратегия — сочетать оба подхода: аналитический и программный.