java.net.InetAddress 是 Java 網絡編程中處理 IP 地址與主機名的核心類。它封裝了數字 IP 地址及其對應的域名,提供了靜態工廠方法創建實例,並內建 10 種判斷特殊 IP 地址類型的方法。本文將系統講解其核心 API、工廠方法、特殊地址分類判斷邏輯,並提供完整可運行的檢測工具代碼。
InetAddress localhost = InetAddress.getLocalHost();
// 輸出示例: hostname/192.168.1.100 (IPv4) 或 hostname/[fe80::...] (IPv6)
// 等價於 localhost (127.0.0.1 / ::1) 但返回真實網卡 IP
注意:多網卡環境下返回第一張非回環網卡 IP,容器化環境可能返回內網 IP。
InetAddress sohu = InetAddress.getByName("www.sohu.com");
// 輸出: www.sohu.com/220.181.38.148
// 若域名對應多個 IP,返回第一個
// 解析失敗拋出 UnknownHostException
InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
// 返回所有解析到的 IP 地址數組 (包含 IPv4/IPv6)
// 至少解析到一個地址才會返回,否則拋出 UnknownHostException
以下方法均為實例方法,返回 boolean。IPv4/IPv6 判斷邏輯不同,下表總結核心範圍:
| 方法名 | 地址類型 | IPv4 典型範圍 / 特徵 | IPv6 典型前綴 / 特徵 | 典型應用場景 |
|---|---|---|---|---|
| isAnyLocalAddress() | 通配符地址 | 0.0.0.0 | :: (0:0:0:0:0:0:0:0) | 服務端綁定所有網卡 (0.0.0.0) |
| isLoopbackAddress() | 回環地址 | 127.0.0.0/8 (127.x.x.x) | ::1 | 本機進程間通信、單元測試 |
| isLinkLocalAddress() | 鏈路本地地址 | 169.254.0.0/16 | fe80::/10 | 無 DHCP 時自動配置、鄰居發現協議 (NDP) |
| isSiteLocalAddress() | 站點本地地址 (已棄用) | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 | fec0::/10 (RFC 3879 已廢棄,改用 ULA fc00::/7) | 企業內網通信 (IPv6 建議用 ULA) |
| isMulticastAddress() | 組播地址 | 224.0.0.0/4 (224.0.0.0 - 239.255.255.255) | ff00::/8 | 視頻會議、股票行情推送、服務發現 |
| isMCGlobal() | 全球組播 | 224.0.1.0 - 238.255.255.255, 239.192.0.0 - 239.255.255.255 (排除保留段) | ff0e::/16 (第2字節 0x0e-0xfe) | 跨互聯網組播 (需路由器支持) |
| isMCLinkLocal() | 鏈路本地組播 | 224.0.0.0/24 (224.0.0.0 - 224.0.0.255) | ff02::/16 (第2字節 0x02) | 路由協議 (OSPF/RIPv2)、mDNS、SSDP |
| isMCNodeLocal() | 節點本地組播 | 無 (IPv4 無此概念) | ff01::/16 (第2字節 0x01) | 單機進程間組播、內核通信 |
| isMCOrgLocal() | 組織本地組播 | 239.192.0.0/14 (239.192.0.0 - 239.195.255.255) | ff08::/16 (第2字節 0x08-0xf8) | 企業內部組播應用 |
| isMCSiteLocal() | 站點本地組播 | 239.255.0.0/16 | ff05::/16 (第2字節 0x05) | 站點範圍內組播 (如校園網) |
利用反射動態調用所有 isXxx() 方法,無需硬編碼即可適配未來 JDK 新增判斷方法:
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IPTypeDetector {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("用法: java IPTypeDetector ");
System.err.println("示例: java IPTypeDetector 224.0.0.1");
System.err.println("示例: java IPTypeDetector FF02::1");
System.err.println("示例: java IPTypeDetector www.google.com");
return;
}
try {
InetAddress address = InetAddress.getByName(args[0]);
System.out.printf("檢測目標: %s (%s)%n", address.getHostAddress(), address.getCanonicalHostName());
System.out.println("----------------------------------------");
Method[] methods = InetAddress.class.getDeclaredMethods();
for (Method method : methods) {
String name = method.getName();
// 匹配以 "is" 開頭、無參數、返回 boolean 的方法
if (name.matches("is[A-Z].*") && method.getParameterCount() == 0 && method.getReturnType() == boolean.class) {
try {
boolean result = (boolean) method.invoke(address);
if (result) {
System.out.printf("✅ %-20s = true%n", name);
}
} catch (Exception e) {
// 忽略調用異常 (如安全限制)
}
}
}
} catch (UnknownHostException e) {
System.err.println("❌ 無法解析主機: " + e.getMessage());
}
}
}
$ java IPTypeDetector 224.0.0.1
檢測目標: 224.0.0.1 (224.0.0.1)
----------------------------------------
✅ isMulticastAddress = true
✅ isMCLinkLocal = true
$ java IPTypeDetector FF02::1
檢測目標: ff02::1 (ff02::1)
----------------------------------------
✅ isMulticastAddress = true
✅ isMCLinkLocal = true
$ java IPTypeDetector 192.168.1.100
檢測目標: 192.168.1.100 (192.168.1.100)
----------------------------------------
✅ isSiteLocalAddress = true
networkaddress.cache.ttl=-1),動態 DNS 環境需調整為合理值 (如 60 秒) 或定期手動刷新。isSiteLocalAddress() 在 IPv6 中語義已變 (ULA),新代碼建議檢測 fc00::/7 (ULA) 替代。UnknownHostException、SocketException,避免單點故障拖垮主線程。InetAddress 是 Java 網絡層的基石,掌握其工廠方法創建實例、理解十大特殊地址判斷邏輯、善用反射編寫通用檢測工具,能顯著提升網絡編程的健壯性與可維護性。結合現代框架 (Netty, Spring Cloud) 的內建解析機制,通常無需直接操作底層 API,但原理掌握是排查疑難雜癥的關鍵。