核心 API:java.net.InetAddress
JDK 內建類別,提供 DNS 解析、本機位址獲取、主機名稱查詢等功能,無需第三方依賴。
完整工具類
package com.example.net;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
public final class DnsResolver {
private DnsResolver() {}
/** 解析域名回傳所有 IP(IPv4/IPv6) */
public static InetAddress[] resolveAll(String hostname) {
try {
return InetAddress.getAllByName(hostname);
} catch (UnknownHostException e) {
return new InetAddress[0];
}
}
/** 解析域名回傳第一個 IP(通常為 IPv4) */
public static InetAddress resolveFirst(String hostname) {
InetAddress[] addrs = resolveAll(hostname);
return addrs.length > 0 ? addrs[0] : null;
}
/** 取得本機所有網卡位址 */
public static InetAddress[] getLocalAddresses() {
try {
return InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
} catch (UnknownHostException e) {
return new InetAddress[0];
}
}
/** 取得本機首選 IPv4 位址 */
public static String getLocalIpv4() {
return Arrays.stream(getLocalAddresses())
.filter(a -> a instanceof java.net.Inet4Address)
.map(InetAddress::getHostAddress)
.findFirst()
.orElse("127.0.0.1");
}
public static void main(String[] args) {
String domain = "www.baidu.com";
System.out.println("=== 本機資訊 ===");
System.out.println("主機名: " + getLocalHostName());
System.out.println("IPv4: " + getLocalIpv4());
System.out.println("所有 IP: " + Arrays.toString(getLocalAddresses()));
System.out.println("\n=== 遠端解析: " + domain + " ===");
InetAddress[] remote = resolveAll(domain);
for (InetAddress addr : remote) {
System.out.printf(" %s (%s)%n", addr.getHostAddress(),
addr instanceof java.net.Inet4Address ? "IPv4" : "IPv6");
}
InetAddress first = resolveFirst(domain);
if (first != null) {
System.out.println("\n首選 IP: " + first.getHostAddress());
}
}
private static String getLocalHostName() {
try { return InetAddress.getLocalHost().getHostName(); }
catch (UnknownHostException e) { return "unknown"; }
}
}
關鍵方法對照表
| 方法 | 回傳 | 說明 |
getByName(host) | InetAddress | 解析單一 IP(取第一筆),會拋出 UnknownHostException。 |
getAllByName(host) | InetAddress[] | 解析所有 IP(含 IPv4/IPv6、多張網卡、負載均衡多 IP)。 |
getLocalHost() | InetAddress | 取得本機回環/首張網卡位址,依 OS 實作而定。 |
getHostAddress() | String | IP 字串格式(IPv4: x.x.x.x,IPv6: xxxx:xxxx:...)。 |
getHostName() | String | 主機名稱(可能觸發反向 DNS 查詢,較慢)。 |
isReachable(timeout) | boolean | ICMP/TCP 探測主機是否可達(需權限,跨平台行為不一)。 |
進階應用:DNS 快取與 TTL 控制
- JDK 內建 DNS 快取,預設 TTL 為
networkaddress.cache.ttl 安全屬性(預設 -1 永久快取)。
- 生產環境建議設定有限 TTL:
-Dsun.net.inetaddr.ttl=60(秒)。
- 若需完全控制(如自定義 DNS 伺服器、DNS-over-HTTPS),請使用
dnsjava 或 Netty Resolver。
常見問題
| 現象 | 原因 | 解決 |
| 解析極慢/卡住 | DNS 伺服器無回應、IPv6 優先但網路不支援 | 設定 -Djava.net.preferIPv4Stack=true 或配置可靠 DNS (8.8.8.8/114.114.114.114) |
| 取到 127.0.0.1 | /etc/hosts 將主機名指向回環 | 修正 /etc/hosts,或用 getAllByName 過濾非回環位址 |
| UnknownHostException | 域名不存在、DNS 故障、離線 | 捕獲異常、重試、降級用備用 IP |
安全提醒
解析結果不可完全信任(DNS 劫持、快取投毒)。安全敏感場景請結合:
- IP 白名單驗證
- TLS 證書驗證(HostnameVerifier)
- Certificate Pinning
- 上一篇文章: Java 通用資料庫操作工具類 DBUtil:支援多資料庫分頁、CRUD、反射映射與註解驅動
- 下一篇文章: Java 陣列元素出現次數統計與字串大小比較工具方法實作
Copyright ©
程式碼之家 All Rights Reserved