InetAddress 如何找到给定主机名的 IP?

问题描述

InetAddress 是如何工作的?它如何找到主机名的 IP 地址。

我知道我们可以在 Java 中使用 InetAddress 进行 DNS 解析,但我想知道它是如何工作的。它如何找到 DNS 服务器来解析地址?

我最近看到一个错误配置的 cname,它没有被 InetAddress 正确解析。它间歇性地得到解决,但大多数时候都失败了。 dig 命令一直在同一台机器上成功。尽管在修复配置后,InetAddress 也始终如一地工作。但我不明白为什么它之前间歇性地成功。要么一直失败,要么成功。

解决方法

根据 Javadoc,Java 的 InetAddress 类使用机器网络配置作为解析主机名的策略。

来自 http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/net/InetAddress.javahttps://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/InetAddress.html(InetAddress 源):

主机名解析 主机名到 IP 地址的解析是通过结合使用本地机器配置信息和网络命名服务(例如域名系统 (DNS) 和网络信息服务 (NIS))来完成的。默认情况下,使用的特定命名服务是本地机器配置的服务。对于任何主机名,返回其对应的IP地址。

这意味着,如果有多个网络,或者为单个网络配置了多个 DNS 服务器,您可能会得到不同的解析结果,因为不同的主机可能会对修复损坏的地址应用不同的宽大处理。

至于为什么另一个应用程序可能更频繁地成功取决于他们的解决策略。

,

如果您使用的是 InetAddress.getByName(String),有几个因素会导致结果不一致:

  1. 它只返回调用 InetAddress.getAllByName(String) 的第一个地址,
  2. 缓存对同一地址的重复查询,即使是负面结果,
  3. 如果查询不在缓存中,则将其转发到平台名称解析服务。对于 WindowsUnixes,这会导致调用 getaddrinfo

这个函数的作用是特定于平台的。在带有 glibc 的 Linux 上,这是通过 gai.confnsswitch.conf 配置的。这会在回退到 /etc/hosts 数据库之前查询许多数据库(几乎总是 dns 文件)。您可以通过以下方式获得类似的结果:

getent hosts <host_name>

总而言之,您使用 dig 获得的只是一长串步骤中的最后一个。