【问题标题】:How does InetAddress find the IP of a given hostname?InetAddress 如何找到给定主机名的 IP?
【发布时间】:2021-01-12 05:06:56
【问题描述】:

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

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

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

【问题讨论】:

    标签: java dns inetaddress


    【解决方案1】:

    根据 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 服务器,您可能会得到不同的解析结果,因为不同的主机可能会对修复损坏的地址应用不同的宽大处理。

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

    【讨论】:

    • 如果它使用机器信息本身,它的输出不应该和dig一样吗?
    • IMO 很可能是 dig 和您的 Java 程序通过本地 DNS 缓存相互影响。让我们假设dig 以某种方式以更智能的方式处理损坏的 CNAME,或者如果无法解析规范的 CNAME,则向服务器发送不同的 DNS 请求变体。这可能会导致回复在 DNS 缓存中存在一段时间,这可能解释了 Java 程序在这些情况下成功的原因。在缓存条目过期后,Java 程序可能无法再次解析它,直到您再次运行 dig。但这纯属猜测。
    • @OptimusPrime,在对我的评论进行一些反馈后,我可以决定是否应该将其变成答案。您可以通过使用这两种工具在调用之间手动清空 DNS 缓存来检验假设。
    【解决方案2】:

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

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

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

    getent hosts <host_name>
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-03
      • 2016-03-29
      • 1970-01-01
      • 2014-02-15
      • 2011-10-11
      • 1970-01-01
      • 2019-08-14
      • 2016-12-02
      相关资源
      最近更新 更多