Java 如何获取URL或IP对应的真实主机名
Java 获取与Ping行为一致的真实主机名方法
原有代码失效的核心原因
你写的这段无法匹配实际场景的代码:
InetAddress.getByName(new URL(url).getHostName());
踩了JDK InetAddress的设计坑:
- 只要
getByName()传入的参数是域名,不是IP格式的字符串,方法就会直接把你传进去的那个域名存在对象的hostName缓存里,根本不会发起反向DNS查询 - 这种逻辑下,不管你传的域名解析到哪个IP、IP反向对应什么主机名,返回值永远是你最开始传入的原始域名,和系统ping的解析逻辑完全不匹配。
你在Linux/Windows上执行ping命令时,拿到的输出根本不是输入的原始域名,它的完整解析流程是:
- 先对输入的域名(比如你敲的
test.com)做正向DNS查询,拿到对应的目标IP(比如151.101.193.69)- 拿着这个IP去查反向DNS的PTR记录,拿到IP绑定的真实主机名(比如你看到的
thisistest.com)- 输出这个反向查到的主机名,而不是最开始输入的那个域名
这也是为什么你ping test.com的时候,开头打印的不是test.com,反而是thisistest.com的原因。
正确实现代码
要拿到和ping输出完全一致的结果,必须完整复刻正向解析+反向解析的流程,代码可以直接用JDK原生能力实现:
import java.net.URL; import java.net.InetAddress; import java.net.UnknownHostException; public class HostResolver { /** * 从URL中获取与系统ping行为一致的真实主机名 * @param urlStr 输入的完整URL字符串,如 "https://test.com/index" * @return 反向解析得到的真实主机名 * @throws UnknownHostException 域名无法解析时抛出异常 */ public static String getRealHostname(String urlStr) throws UnknownHostException { // 1. 从URL中提取不带端口、路径的原始host字符串 String originalHost = new URL(urlStr).getHost(); // 2. 正向解析原始host,拿到对应的IP地址 InetAddress forwardAddress = InetAddress.getByName(originalHost); // 3. 用IP地址再次构造InetAddress对象,强制触发反向DNS查询 String ipAddr = forwardAddress.getHostAddress(); InetAddress reverseAddress = InetAddress.getByName(ipAddr); // 4. 此时拿到的主机名与系统ping输出完全一致 return reverseAddress.getHostName(); } }
实际使用的注意点
- 如果目标域名配置了多IP负载均衡,别用
getByName只拿第一个IP,可以通过InetAddress.getAllByName(originalHost)遍历所有解析到的IP,逐个做反向解析,就能拿到和ping实际连通的节点对应的主机名 - 反向DNS查询需要走53端口,如果你的运行环境封锁了53端口的UDP流量,就拿不到预期的主机名,这时候返回的就是IP本身——这和你在同样网络环境下ping遇到查不到PTR记录时的表现完全一致
- 别在循环里高频调用这个方法,DNS查询存在网络延迟,高频使用时建议增加本地缓存,避免不必要的性能损耗
内容的提问来源于stack exchange,提问作者Neethu Lalitha
相关产品推荐
相关产品推荐

