InetAddress 代表 IP 地址(IPv4/IPv6),提供本機地址獲取、域名解析、主機名反查等功能。
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
public class DomainIpResolver {
public static void main(String[] args) {
// 1. 獲取本機 IP
try {
InetAddress local = InetAddress.getLocalHost();
System.out.println("本機主機名:" + local.getHostName());
System.out.println("本機 IP:" + local.getHostAddress());
} catch (UnknownHostException e) {
System.err.println("獲取本機地址失敗:" + e.getMessage());
}
// 2. 解析域名所有 IP(支援多 IP、CDN、負載均衡)
String domain = "www.google.com"; // 測試域名
System.out.println("\n解析域名:" + domain);
resolveDomain(domain);
// 3. 反查:IP 獲取主機名
try {
InetAddress ip = InetAddress.getByName("8.8.8.8");
System.out.println("\n8.8.8.8 主機名:" + ip.getHostName());
} catch (UnknownHostException e) {
System.err.println("反查失敗:" + e.getMessage());
}
}
/** 解析域名並列印所有 IP */
public static void resolveDomain(String domain) {
try {
InetAddress[] addresses = InetAddress.getAllByName(domain);
System.out.println("共解析到 " + addresses.length + " 個 IP:");
for (int i = 0; i < addresses.length; i++) {
InetAddress addr = addresses[i];
System.out.printf(" IP %d: %s (%s)%n",
i + 1,
addr.getHostAddress(),
addr instanceof java.net.Inet6Address ? "IPv6" : "IPv4");
}
} catch (UnknownHostException e) {
System.err.println("域名解析失敗:" + e.getMessage());
}
}
}
| 方法 | 用途 | 回傳 | 異常 |
|---|---|---|---|
getLocalHost() | 獲取本機地址 | InetAddress | UnknownHostException |
getByName(host) | 解析域名/IP,取第一個 | InetAddress | UnknownHostException |
getAllByName(host) | 解析域名所有 IP | InetAddress[] | UnknownHostException |
getHostAddress() | 取得 IP 字串 | String | - |
getHostName() | 取得主機名(反查 DNS PTR) | String | - |
isReachable(timeout) | ICMP/TCP 探測連通性 | boolean | IOException |
JVM 預設緩存正向解析結果 永久(networkaddress.cache.ttl=-1),負向緩存 10 秒。生產環境需調整:
// 安全策略文件或啟動參數
-Dsun.net.inetaddr.ttl=60 # 正向緩存 60 秒
-Dsun.net.inetaddr.negative.ttl=10 # 負向緩存 10 秒
或代碼動態設置(需權限):
java.security.Security.setProperty("networkaddress.cache.ttl", "60");
// 只取 IPv4
Arrays.stream(InetAddress.getAllByName(domain))
.filter(addr -> addr instanceof java.net.Inet4Address)
.findFirst()
.ifPresent(addr -> System.out.println("IPv4: " + addr.getHostAddress()));
// 使用 CompletableFuture 避免阻塞主執行緒
CompletableFuture.supplyAsync(() -> {
try { return InetAddress.getAllByName(domain); }
catch (UnknownHostException e) { throw new RuntimeException(e); }
}).thenAccept(addrs -> {
// 異步處理結果
});
getLocalHost() 在 Docker 中可能返回容器內部 IP(如 172.17.0.2)而非宿主機 IP。| 錯誤 | 原因 | 解決 |
|---|---|---|
| UnknownHostException | DNS 解析失敗、域名錯誤、網路不通 | 檢查 /etc/resolv.conf、nslookup 驗證、防火牆 |
| 返回 127.0.0.1 | /etc/hosts 配置錯誤、主機名映射回環 | 修正 hosts、檢查 hostname 指令 |
| 緩存導致 IP 不更新 | JVM DNS 緩存 TTL 過長 | 設置 networkaddress.cache.ttl |
InetAddress 是 Java 網路編程基石,掌握 getAllByName 多 IP 處理、緩存控制、IPv6 適配、容器化環境坑點,能構建健壯的網路服務發現與通訊模組。