Суперполезный JIP-Common: поддержка IPv4 и IPv6
С постепенным внедрением IPv6 во внутренние приложения многих компаний, возникает необходимость в поддержке IPv6. Однако, из-за того что большинство разработчиков ранее учитывали только IPv4, обновление поддержки IPv6 может быть сложным процессом, который может привести к большому количеству кода с использованием if else.
JIP-common — это модуль для анализа IP-адресов, который скрывает от верхних слоёв приложения детали, связанные с IP-типами и IP-диапазонами. Это делает процесс обновления более удобным.
Для получения дополнительной информации посетите следующие ссылки:
Введение в JIP-common
JIP-common не только поддерживает IPv4 и IPv6, но также может анализировать различные форматы IP (см. следующий раздел). Он позволяет верхним слоям приложения игнорировать тип IP и даже отдельные IP или диапазоны IP, делая код верхнего уровня более лаконичным.
Поскольку большинству бизнес-приложений требуется работа с наборами IP-адресов, JIP предоставляет функции для работы с этими наборами, такие как объединение, пересечение, объединение и разность, чтобы максимально удовлетворить потребности бизнеса.
Обычно разработчики используют хеш-таблицу для поиска IP-адреса, соответствующего определённому продукту. Для этого они преобразуют диапазон IP-адресов в отдельные IP-адреса и сопоставляют их с помощью карты. Этот подход работает хорошо, если количество IP-адресов невелико. Но при работе с IPv6 или большим количеством IP-адресов этот метод становится неэффективным.
Чтобы решить эту проблему, JIP использует бинарные деревья и красно-чёрные деревья для быстрого поиска. Это значительно сокращает использование памяти и время поиска.
Поддерживаемые форматы
Для строк, начинающихся с #, JIP рассматривает их как комментарии и пропускает анализ. В качестве разделителей между IP-адресами можно использовать \r\n, \r, \n или ;.
3.1. Поддерживаемые форматы для IPv4 и IPv6
Формат | Пример | Примечание |
---|---|---|
IPv4 | 1.1.1.1 | Комментарии не должны содержать разделитель, так как он будет интерпретирован как разделитель между несколькими IP-адресами. |
Диапазон IPv4 с маской | 1.1.1.1/24 | Комментарии не должны содержать разделитель. |
Простой диапазон IPv4 | 1.1.1.1-20 | Комментарии не должны содержать разделитель. |
Полный диапазон IPv4 | 1.1.1.1–1.1.1.20 | Комментарии не должны содержать разделитель. |
Формат | Пример | Примечание |
---|---|---|
IPv6 | 8888::226:2dff:fefa:0 | Комментарии не должны содержать разделитель. |
Диапазон IPv6 с маской | 8888::226:2dff:fefa:0/24 | Комментарии не должны содержать разделитель. |
Простой диапазон IPv6 | 8888::226:2dff:fefa:0–20 | Комментарии не должны содержать разделитель. |
Полный диапазон IPv6 | 8888::226:2dff:fefa:0–8888::226:2dff:fefa:20 | Комментарии не должны содержать разделитель. |
3.2. Наборы IP-адресов
JIP предоставляет интерфейс JIPAddress для одного IP-адреса или диапазона и реализует набор JIPAddressSet на основе бинарных деревьев и красно-чёрных деревьев. Этот набор может содержать все поддерживаемые форматы IPv4 и IPv6.
Верхние слои приложения могут работать с этим набором без учёта того, является ли IP-адрес IPv4 или IPv6 и представляет ли он отдельный IP-адрес или диапазон.
Быстрое использование
Подробные руководства обычно читают редко, поэтому мы рассмотрим использование JIP на конкретных примерах.
4.1. Сценарий 1: Анализ IP-адресов
Анализ отдельного IP-адреса или диапазона можно выполнить следующим образом:
JIPAddress a1 = JIPAddressUtils.toIpObject("10.0.0.5/24 # Это комментарий");
System.out.println(a1.toString()); // 10.0.0.5/24
JIPAddress a2 = JIPAddressUtils.toIpObject("10.0.0.0-255");
JIPAddress a3 = JIPAddressUtils.toIpObject("8888::226:2dff:fefa:10-8888::226:2dff:fefa:20")
Если вы хотите узнать тип проанализированного адреса, вы можете вызвать функцию getIpType(), которая вернёт значение перечисления.
System.out.println(a1.getIpType())
При анализе нескольких IP-адресов или диапазонов можно использовать следующий метод:
JIPAddressSet addressSet = JIPAddressUtils.buildAddressSet(
"101.35.129.0;101.35.132.0/24;101.35.133.0/24;101.35.134.0/24;101.35.135.0/24;");
Это позволит создать набор IP-адресов. Можно использовать четыре типа разделителей [\r\n, \r, \n и ;] для разделения нескольких IP-адресов и диапазонов. IPv4 и IPv6 могут сосуществовать, и комментарии не вызовут проблем.
JIPAddressUtils.isValidIPAddress("1.1.1.1")
4.2. Сценарий 2: Объединение IP-адресов Объединение IP-адресов предназначено для уменьшения количества записей IP. Например, 1.1.1.0–100 и 1.1.1.100–255 можно объединить в 1.1.1.0/24. JIP поддерживает объединение отдельных IP-адресов (диапазонов) и множественных IP-адресов (диапазонов), которое выполняется JIPAddressCombiner.
Пример объединения отдельных IP-адресов:
JIPAddress jipAddress1 = JIPAddressUtils.toIpObject("1.1.1.0");
JIPAddress jipAddress2 = JIPAddressUtils.toIpObject("1.1.1.1-255");
List<JIPAddress> result = JIPAddressCombiner.combine(jipAddress1, jipAddress2);
// Результат: 1.1.1.0/24
Объединение множественных IP-адресов работает аналогично.
4.3. Сценарий 3: Пересечение IP-адресов Функция пересечения IP-адресов позволяет находить общие IP-адреса между двумя или более диапазонами. Эта функция реализуется JIPAddressIntersecter.
Пример пересечения отдельных IP-адресов:
JIPAddress jipAddress1 = JIPAddressUtils.toIpObject("1.1.1.15-30");
JIPAddress jipAddress2 = JIPAddressUtils.toIpObject("1.1.1.10-20");
List<JIPAddress> result = JIPAddressIntersecter.intersect(jipAddress1, jipAddress2);
// Результат: 1.1.1.15–20
Пересечение множественных IP-адресов также работает аналогичным образом. 4.4 Сцена 4: IP-адресное объединение
IP-адресное объединение — это не только поиск одного IP (сегмента), но и пересечение между несколькими IP (сегментами). Эта функция в основном выполняется с помощью JIPAddressUnioner.
Пример объединения одного IP (сегмента):
JIPAddress address1 = JIPAddressUtils.toIpObject("101.35.135.0/24"); JIPAddress address2 = JIPAddressUtils.toIpObject("101.35.136.0/21"); List addressList = JIPAddressUnioner.union(address1, address2);
Аналогично, объединение нескольких IP (сегментов) также похоже.
4.5 Сцена 5: IP-адресная разность
Функция IP-адресной разности позволяет не только искать один IP (сегмент), но и находить разницу между несколькими IP (сегментами), что выполняется с использованием JIPAddressSubtracter.
Пример разности одного IP (сегмента):
JIPAddress address1 = JIPAddressUtils.toIpObject("101.35.135.0/24"); JIPAddress address2 = JIPAddressUtils.toIpObject("101.35.135.0/28"); List addressList = JIPAddressSubtracter.subtract(address1, address2);
Подобно этому, разность нескольких IP (сегментов) аналогична.
4.6 Сцена 6: Отображение IP на группы
Поиск
Это наиболее распространённый сценарий, когда группа содержит множество IP (сегментов), и необходимо быстро найти соответствующий IP для группы. Обычно мы используем метод, при котором IP-сегменты хэшируются по одному, а затем помещаются в HashMap. Проблема этого метода заключается в том, что количество IP должно быть в определённом диапазоне. Если есть сегмент A или даже 0.0.0.0/0, программа может использовать большое количество памяти и даже вызвать сбой программы.
Рекомендуется использовать набор модулей библиотеки JIP, которые позволяют быстро создавать небольшие красно-чёрные деревья, как показано ниже:
// Создание пустого набора JIPAddressSet tmpJipAddressSet = JIPAddressUtils.buildEmptyAddressSet(); for (IdcIpSegment idcIpSegment : tmpIdcIpSegmentList) { // Помещаем список IP для этой группы в набор вместе с данными внешнего ключа, соответствующими группе JIPAddressUtils.addIpList(tmpJipAddressSet, idcIpSegment.getIpList(), idcIpSegment); }
Тогда как найти IP для соответствующей группы? Например, если в группе есть IP 1.1.1.0/24, мы можем выполнить следующий запрос:
JIPAddress find = jipAddressSet.findIp("1.1.1.23")
В этом случае результатом поиска будет 1.1.10/24, и мы сможем получить соответствующую группу:
IdcIpSegment findGroup = ((IdcIpSegment) find.getData())
Эти две операции можно объединить в одну, и оба метода эквивалентны:
IdcIpSegment findGroup = jipAddressSet.findIpData("1.1.1.23", IdcIpSegment.class);
Примечание: если есть несколько совпадений, findIp возвращает только первое совпадение. Также обратите внимание, что преобразование набора в список требует вызова all() для сбора данных с использованием предварительного порядка.
Обновление
Если вы хотите удалить IP из набора, просто вызовите JIPAddressSet.deleteIp(). Важно отметить, что удаление является полным соответствием, в то время как поиск является частичным соответствием (достаточно пересечения). Например:
JIPAddressSet tmpJipAddressSet = JIPAddressUtils.buildEmptyAddressSet(); JIPAddressUtils.addIpList(tmpJipAddressSet,“1.1.1.0/24”, idcIpSegment); tmpJipAddressSet.deleteIp("1.1.1.0"); // Невозможно удалить tmpJipAddressSet.deleteIp("1.1.1.0/24"); // Можно удалить tmpJipAddressSet.deleteIp("1.1.1.0-255"); // Можно удалить
4.7 Сцена 7: Проверка добавленных IP-адресов
Проверка эффективности
При добавлении IP-групп обычно проверяют, действителен ли введённый IP-адрес. Библиотека JIP предоставляет простой класс анализа проверки, который останавливается после обнаружения первой ошибки и возвращает сообщение об ошибке:
String check = JIPAddressCheckUtils.checkConvertIpObject(addressList, departmentIPSegment.getIpList()); if (StringUtils.isNotBlank(check)) { // Если есть ошибка, она будет отображаться return check; }
Проверка конфликтов
При обновлении IP-группы необходимо проверить, не конфликтует ли обновление с существующими группами. Обычный метод заключается в следующем:
4.8 Сцена 8: Форматирование вывода
Форматирование влияет только на формат вывода IP-сегмента, но не на отдельные IP. Оно всегда выводит отдельный IP в одном стиле.
Форматирование
JIPAddress address = JIPAddressUtils.toIpObject("1.2.3.0-255"); System.out.println(address.toString()); // ===> 1.2.3.0-255 System.out.println(JIPAddressUtils.toIpListString(address, IPFormatType.SEGMENT_WITH_MASK_FIRST)); // ==> 1.2.3.0/24 System.out.println(JIPAddressUtils.toIpListString(address, IPFormatType.SEGMENT_SIMPLE_FIRST)); // ===> 1.2.3.0-255 System.out.println(JIPAddressUtils.toIpListString(address, IPFormatType.SEGMENT_FULL_FIRST)); // 1.2.3.0-1.2.3.255
Формат вывода определяет, какой формат используется для вывода, и если указанный формат не может быть использован, он автоматически возвращается к исходному формату. Например, 1.2.3.1-3 этот IP-сегмент не может быть выведен в формате с маской, поэтому даже если указан формат маски, он не будет работать.
JIPAddress address = JIPAddressUtils.toIpObject("1.2.3.1-3"); System.out.println(address.toString()); // ====> 1.2.3.1-3 System.out.println(JIPAddressUtils.toIpListString(address, IPFormatType.SEGMENT_WITH_MASK_FIRST)); // ====> 1.2.3.1-3 System.out.println(JIPAddressUtils.toIpListString(address, IPFormatType.SEGMENT_SIMPLE_FIRST)); // ====> 1.2.3.1-3 System.out.println(JIPAddressUtils.toIpListString(address, IPFormatType.SEGMENT_FULL_FIRST)); // ====> 1.2.3.1-1.2.3.3
4.9 Сцена 9: Расширение IP-сегмента
К сожалению, без контекста исходного запроса невозможно точно определить, о чём идёт речь в этой сцене. Однако, исходя из предоставленного текста, можно предположить, что здесь описывается процесс расширения IP-сегмента путём добавления новых IP-адресов или изменения существующих. Если необходимо развернуть IP-диапазон в список отдельных IP-адресов, то обычно используется метод JIPAddressUtils.expandIpList:
List<JIPAddress> ipList = JIPAddressUtils.expandIpList(
JIPAddressUtils.toIpObject("1.1.1.1/24"), 10);
В итоге с помощью итератора получается список из первых 10 IP-адресов (второй параметр указывает максимальное количество IP-адресов для вывода, 0 означает отсутствие ограничений).
Кроме работы с IP-диапазоном, можно также развернуть отдельные IP-адреса или несколько IP-адресов (диапазонов):
List<JIPAddress> ipList = JIPAddressUtils.expandIpList(JIPAddressUtils.buildAddressSet("1.1.1.1/30\n2.2.2.2/30"), 0);
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )