W3docs

Java InetAddress

Разрешение и представление IP-адресов в Java с помощью класса InetAddress.

Каждое соединение в этом разделе требовало адреса — хоста и порта. java.net.InetAddress — это класс, представляющий хостовую часть: IP-адрес, опционально сопровождённый именем хоста. Он также является шлюзом к DNS (системе доменных имён), преобразующей имя вроде example.com в числовой адрес, по которому реально маршрутизируется сеть. Этот финальный раздел о сетях рассматривает создание, разрешение и проверку адресов. Те же экземпляры InetAddress, которые вы здесь создаёте, передаются в Socket, ServerSocket или DatagramSocket для фактического подключения.

Нет публичного конструктора — используйте фабричные методы

Никогда не пишите new InetAddress(...). Вместо этого:

InetAddress a = InetAddress.getByName("example.com");   // DNS lookup (or parse a literal)
InetAddress b = InetAddress.getByName("93.184.216.34"); // numeric literal: no DNS
InetAddress[] all = InetAddress.getAllByName("example.com"); // every address for a host
InetAddress lo = InetAddress.getLoopbackAddress();      // 127.0.0.1 / ::1, never fails
InetAddress me = InetAddress.getLocalHost();            // this machine's address
InetAddress c = InetAddress.getByAddress(new byte[]{10,0,0,1}); // from raw bytes

Ключевое различие: getByName с именем хоста выполняет DNS-запрос (который может быть медленным или бросить UnknownHostException без сети); с числовым литералом — просто парсит без обращения к сети. getByAddress строит адрес из сырых байт без какого-либо поиска.

Когда это нужно? Всякий раз, когда требуется разрешить имя перед подключением, проверить или классифицировать адрес (loopback, приватный, multicast), или сохранить кэшированный адрес, чтобы избежать повторных DNS-запросов на горячем пути. Высокоуровневые помощники, такие как класс URL, разрешают хосты за кулисами; InetAddress — это уровень, к которому вы обращаетесь, когда нужен сам адрес.

IPv4 и IPv6

InetAddress — общий супертип; конкретные экземпляры — это Inet4Address (32-битный, 93.184.216.34) или Inet6Address (128-битный, ::1). getAddress() возвращает сырые байты (4 или 16), а getHostAddress() — каноническое текстовое представление. Код должен работать с обоими семействами единообразно через тип InetAddress.

Инспектирование адреса

Полезные предикаты классифицируют адрес без обращения к сети: isLoopbackAddress(), isSiteLocalAddress() (приватные диапазоны вроде 10.x / 192.168.x), isMulticastAddress(), isAnyLocalAddress() (шаблонный адрес 0.0.0.0) и isReachable(timeout) (реальная проверка наподобие ping — единственный метод здесь, который действительно обращается к сети).

Практический пример: создание и классификация адресов

Эта программа создаёт адреса несколькими способами — loopback, IPv4-литерал, сырые байты, IPv6-литерал — и проверяет каждый с помощью предикатов классификации. Намеренно используются литералы и loopback, чтобы программа работала без сети; единственный вызов, зависящий от DNS (getLocalHost), защищён.

java— editable, runs on the server

Что следует вынести из результата выполнения:

  • Адреса создавались без конструктора — каждый экземпляр получен из фабрики: getLoopbackAddress, getByName, getByAddress. Такой дизайн позволяет JVM кэшировать запросы и возвращать правильный подкласс (Inet4Address или Inet6Address).
  • getByName("93.184.216.34") и getByName("::1") не выполняли DNS-запрос, поскольку аргументы были числовыми литералами — метод просто их разобрал. Тот же вызов с именем хоста обратился бы к DNS, что медленно и ненадёжно без сети; важно знать, какие входные данные вызывают поиск.
  • Количество сырых байт различало семейства: IPv4-адрес вернул 4 байта, IPv6 — 16, а instanceof Inet6Address подтвердил конкретный тип. Код, работающий с адресами обобщённо, использует супертип InetAddress и редко нуждается в ветвлении по семейству.
  • Предикаты классификации отвечали на структурные вопросы без обращения к сети: loopback-адрес вернул true для isLoopbackAddress(), а 10.0.0.1, построенный из байт, вернул true для isSiteLocalAddress() (приватный диапазон). Эти проверки — чистая арифметика над байтами адреса.
  • getLocalHost() был обёрнут в try/catch, потому что может завершиться с UnknownHostException, если имя машины не разрешается. Разрешение адреса — это по существу сетевая/DNS-операция, которая может дать сбой, поэтому надёжный код всегда учитывает случай неудачного разрешения — такая же осторожность применялась в каждой главе этого раздела к самой сети.

Практика

Практика
Чувствительный к задержкам сервис вызывает 'InetAddress.getByName(host)' в плотном цикле, где 'host' иногда является доменным именем, а иногда числовым IP-литералом. Профилирование выявляет периодические задержки в несколько сотен миллисекунд. В чём лучшее объяснение?
Чувствительный к задержкам сервис вызывает 'InetAddress.getByName(host)' в плотном цикле, где 'host' иногда является доменным именем, а иногда числовым IP-литералом. Профилирование выявляет периодические задержки в несколько сотен миллисекунд. В чём лучшее объяснение?
Was this page helpful?