О задании
В прошлых статьях мы не только разобрались с работой модели OSI, но и научились пользоваться функциями модуля ipaddress в Python. Теперь можем смело переходить к разбору алгоритмов решения 13 заданий ЕГЭ по информатике.
Данное задание направлено на проверку умений определять параметры по заданному IP-адресу и маске подсети, рассчитывать количество возможных адресов в сети, а также на применение побитовых операций для работы с IP-адресами и масками.
Работать в данном задании предстоит всего с тремя значениями: адрес сети, адрес узла и маска подсети. Два из них даются в условии, а одно требуется найти. Задания 13 можно разделить на 7 типов, в зависимости от данных значений:
- Даны адрес узла и маска. Чаще всего в таких заданиях требуется найти наибольший адрес сети, который может быть назначен компьютеру;
- Даны два адреса узлов, находящихся в одной сети. Требуется найти маску (наибольшее/наименьшее количество единиц/нулей в маске) или количество адресов в этой сети;
- Даны адрес узла и адрес сети. Обычно требуется найти маску подсети (наибольшее/наименьшее количество единиц/нулей);
- Даны адрес сети и маска. Требуется найти количество адресов в сети, удовлетворяющих условию, например, количество нулей/единиц в IP-адресе кратно какому-то числу и т.д.;
- Даны маска и адрес узла с неизвестным байтом. Требуется найти значение отсутствующего байта адреса узла, при котором будет выполняться условие (количество единиц/нулей в левых двух байтах меньше/больше количества в правых двух байтах);
- Даны маска и адрес сети с неизвестным байтом. Требуется найти значение отсутствующего байта адреса сети, при котором будет выполняться условие (количество единиц/нулей в левых двух байтах меньше/больше количества в правых двух байтах);
- Даны адрес сети и маска с неизвестным байтом. Требуется найти значение отсутствующего байта маски, при котором будет выполняться условие (количество единиц/нулей в левых двух байтах меньше/больше количества в правых двух байтах);
Типов слишком много для одной статьи, так что мы разобьём их разбор на три части. В данной статье рассмотрим первые 2 типа заданий, в следующей поговорим про ручные и программные методы решения 3-4 типов, а напоследок разберём все задания с неизвестным байтом.
Алгоритм решения
Решать 13 задания мы будем по большей части программными методами с помощью встроенного в Python модуля ipaddress. Если вы еще не умеете работать с данным модулем, то настоятельно рекомендуем сначала ознакомиться с прошлой статьёй.
Во всех формулировках заданий далее мы будем опускать общую часть и приводить только основную информацию, нужную для решения.
Тип 1
Начнём с самого простого типа, задания которого удивительно часто стали попадаться на экзамене.
Рассмотрим такую формулировку:
«Сеть задана IP-адресом одного из входящих в неё узлов 98.81.154.195 и сетевой маской 255.252.0.0.
Найдите наибольший в данной сети IP-адрес, который может быть назначен компьютеру.»
Здесь буквально всё решение занимает пару строчек. Сначала импортируем функцию ip_interface() и создаём объект IP-интерфейса:
Вспоминаем, что последний (с индексом -1) адрес является широковещательным. Значит, нам нужно взять предпоследний (с индексом -2) и вывести на экран:
Мы получаем такой адрес: 98.83.255.254. Осталось лишь удалить из него точки и записать в ответ.
Пример 1
Рассмотрим задание немного посложнее:
«Сеть задана IP-адресом одного из входящих неё узлов 190.202.83.62 и сетевой маской 255.255.252.0.
Найдите наибольший IP-адрес в данной сети, который может быть назначен компьютеру. В ответе укажите сумму числовых значений октетов найденного IP-адреса.»
Уже интереснее, здесь нужно не только найти адрес, но и просуммировать значения его октетов. С первой частью мы справимся без проблем:
Теперь нужно как-то из переменной last_ip достать значения, разделённые точками. Сделаем это через списочное включение:
Что у нас тут происходит? Для начала мы приводим объект IP-адреса к строчному типу данных: str(last_ip). Затем разделяем строку по символу точки: str(last_ip).split(«.»).
Проходимся по полученному списку и каждую строку в нём приводим к целочисленному типу данных: int(octet) for octet in str(last_ip).split(«.»). В конце собираем все целые числа в один список, чтобы проще было просуммировать их.
Для любителей функции map() — те же действия можно записать так:
Останется лишь вывести на экран сумму чисел в списке octets:
Запускаем программу и получаем число 729, которое и запишем в ответ.
Пример 2
И для закрепления рассмотрим еще одно задание:
«Сеть задана IP-адресом одного из входящих в неё узлов 191.128.66.83 и сетевой маской 255.192.0.0.
Найдите в данной сети наибольший IP-адрес, который может быть назначен компьютеру. В ответе укажите найденный IP-адрес без разделителей.»
Что же, не будем просто дублировать одинаковый код. Давайте в этот раз покажем максимально «питоническое» решение в одну строку:
А если чувствуете, что можете ошибиться в переписывании адреса с этими точками-разделителями, то лучше вовсе избавиться от них вот таким образом:
В результате получим строку 191191255254, которую можно сразу записать в ответ.
Тип 2
Задания второго типа чаще всего имеют только авторские формулировки. Но в любом случае будет полезно научиться их решать. Начнём с такого:
«Два узла, находящиеся в одной сети, имеют IP-адреса 127.0.1.65 и 127.0.1.101.
Укажите наименьшее возможное количество адресов в этой сети.»
Определим алгоритм действий:
- Сначала создадим по объекту на каждый IP-адрес;
- Затем в цикле будем перебирать возможные префиксы маски. Так как нам нужно наименьшее количество адресов, то следует начать со значения 30 и идти на убывание с шагом 1;
- Строим сеть по первому IP-адресу (любому из двух);
- Проверяем, попадает ли второй в эту же сеть;
- Дополнительно проверяем, что оба адреса не служебные — не адреса сети и не широковещательные.
Переходим к решению. Импорт и создание объектов:
Далее перебираем значения маски от 30 до 0 с шагом 1:
Строим сеть по первому адресу:
Теперь проверим условия:
- ip2 входит в сеть net;
- ip1 и ip2 — не служебные. Здесь удобно будет проверить принадлежность к net.hosts().
Как только выполнится условие — выводим количество адресов в этой сети и завершаем цикл:
Здесь требуется количество всех адресов, так что никаких «-2» мы не делаем. Запускаем программу и видим число 64. Его и запишем в ответ.
Пример 1
Заключительное задание будет таким:
«Два узла, находящиеся в одной сети, имеют IP-адреса 192.168.190.12 и 192.168.184.0.
Укажите наибольшее возможное количество единиц в маске этой сети.»
Сразу вспоминаем, что количество единиц в маске — это как раз длина префикса, которую мы и перебираем в цикле. Значит, теперь нужно будет вывести на экран значение переменной mask. В остальном код практически без изменений:
Запускаем его и получаем число 20, которое и будет ответом на это задание.
На это и закончим разбор первых 4 типов 13 заданий. В следующей статье научимся решать оставшиеся 3 типа, в которых предстоит работать с неизвестными байтами в маске и адресах сети или узла.
Пример 2
Напоследок решим задание посложнее:
«Два узла, находящиеся в разных подсетях, имеют IP-адреса 192.168.34.17 и 192.168.45.91. Известно, что в масках обеих подсетей содержится одинаковое количество единиц.
Определите наименьшее возможное количество единиц в масках этих подсетей.»
Снова ищем количество единиц, но теперь узлы находятся уже в разных сетях! И теперь нам не обойтись без построения обеих сетей.
Начинаем как обычно, импортируем функции и создаём два объекта IP-адреса:
Видим одинаковые числа в первых двух байтах, так что уверенно заявляем, что маска меньше 16 быть не может:
Теперь строим сети с разными узлами, но одинаковой длиной префикса (или маской):
Что нам нужно проверить здесь? Во-первых, что сети разные, то есть не равны друг другу. Во-вторых, что первый IP-адрес не является служебным и входит в первую сеть. Аналогично и со вторым:
Нам нужно наименьшее количество единиц в маске, следовательно и наименьшая длина префикса. Тогда, как только выполнятся все условия, выводим текущее значение переменной mask на экран и завершаем цикл:
Готово, теперь запускаем код и радуемся ответу на это задание — числу 21.
На этом мы закончим с первыми двумя типами 13 заданий. В следующей статье разберём типы посложнее и также научимся решать некоторые из них ручными методами.