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), защищён.
Что следует вынести из результата выполнения:
- Адреса создавались без конструктора — каждый экземпляр получен из фабрики:
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-операция, которая может дать сбой, поэтому надёжный код всегда учитывает случай неудачного разрешения — такая же осторожность применялась в каждой главе этого раздела к самой сети.