【问题标题】:Can InetAddress represent host names that can't be resolved?InetAddress 可以代表无法解析的主机名吗?
【发布时间】:2010-10-30 17:57:10
【问题描述】:

我用网络信息解析各种数据源。

我一直在使用java.net.InetAddress 来表示和解析主机。使用 IP 初始化它可以正常工作。

我现在必须解析一个新源。它包含主机名而不是 IP。 InetAddress.getByName() 如果无法将主机名参数解析为 IP,则抛出 UnknownHostException。主机 IP 对于我的目标并不是绝对必要的。仅仅因为 DNS 故障而丢弃数据对我来说是不可接受的。

如果可以获取,我想要一个 IP 地址,否则我想要一个主机名。

如何防止给定主机名的解析?还有其他更适合我需要的课程吗?

【问题讨论】:

    标签: java networking


    【解决方案1】:

    InetAddress.getByAddress(String host, byte[] addr) 方法不执行对 DNS 的查询,并允许您创建具有任意主机名和 IP 地址的 InetAddress,可能是 IPv4 未指定地址 (0.0.0.0)。

    尝试使用getByName 创建InetAddress,如果出现问题,您可以使用getByAddress 创建它。请注意,您需要在实际使用 IP 地址之前检查它们是否有效。


    示例代码:

    公共静态无效主要(字符串arg []) 抛出 UnknownHostException { 网络地址一个; 字节[] unspec = 新字节[4]; 不规范[0]=0; 不规范[1]=0; 不规范[2]=0; 不规范[3]=0; 尝试 { a = InetAddress.getByName(arg[0]); } 捕获(未知主机异常 e) { a = InetAddress.getByAddress(arg[0],unspec); } System.out.println(a); }

    【讨论】:

    • 这将生成 InetAddress 对象,其中主机名和 ip-address 不适合。特别是0.0.0.0 是为default network 保留的。
    • 我相信这个答案最接近我的需要。不幸的是,零 IP 破坏了 InetAddress 的比较功能,这对我的需求不利。
    • 感谢您,我正在寻找一种使用 3rd 方 api 模拟 InetAddress 对象的方法。对于我的使用,api 必须使用 InetAddress,但名称很重要,但 ipaddress 不重要。
    【解决方案2】:

    我猜这是不可能的,因为InetAddress的核心功能是处理IP-Addresses:

    这个类代表一个互联网 协议 (IP) 地址。

    IP 地址是 32 位或 IP 使用的 128 位无符号数,a 底层协议 建立了UDP和TCP等协议。 定义了 IP 地址架构 由 RFC 790:分配的编号,RFC 1918:私人地址分配 互联网,RFC 2365:管理上 范围 IP 多播和 RFC 2373:IP 版本 6 寻址架构。一个 InetAddress 的实例包括 一个 IP 地址,可能还有它的 对应的主机名(取决于 是否用主机构建 名称或是否已经完成 反向主机名解析)。

    你不可能在没有 IP 地址的情况下构造一个 InetAddress 对象。

    出于您的目的,您需要定义一个 Hostname.class,其中包含主机名和可能的附加数据。如果您使用的是 Java 6,则此类应该/可以通过 IDN 处理所有域名国际化。如果您使用的是 Java 5,则可以使用单独的 IDN 库。

    单独的 Hostname.class 还可以定义守卫或构造函数,根据相关 RFC 确保仅有效的主机名。

    【讨论】:

    • 试着用InetAddress.getByName("google.com") 行编写一个简单的程序,你会发现这里错了。
    • 当然,因为google.com 有一个IP 地址。如果您希望我证明错误,请告诉我如何从某种 DNS 获取没有现有 IP 地址的主机名的 InetAddress 对象。这就是这个问题的全部内容。并删除您的反对票,因为您错了。
    • 我想,我明白你和@Basilevs 在说什么。现在这个问题在我看来很奇怪,因为实际上没有真正的 IP 地址的主机的简单字符串和“inet 地址”之间没有任何区别。
    • @Roman:这是问题:Can InetAddress represent host names that can't be resolved?
    • @Roman:阅读文档 - “此类表示 Internet 协议 (IP) 地址”。有多种静态辅助方法可以通过执行 DNS 查找来创建 InetAddress 对象,但是如果没有匹配的 DNS 记录,则无法创建 InetAddress - 事实上,这样做是没有意义的(因为一开始没有 IP 地址)。
    【解决方案3】:

    写一个新类怎么样?它只需要能够存储一个字符串和一个 InetAddress。

    【讨论】:

      【解决方案4】:

      通过编辑/etc/hosts 文件解决了问题:

      我也有类似的问题(InetAddress.getByName 不使用主机名)。

      我通过删除诸如 ::1 localhostff81::1%lo0 localhost 之类的条目解决了这个问题,只有 127.0.0.1 localhost。

      我删除了 localhost 的其余条目。我为我的 Mac 做了这个。

      有时,我提供的任何信息都不起作用。在这种情况下,我只是将文件 /etc/hosts 文件移动到 hosts_backup。然后恢复文件。即将文件hosts_backup 移动到/etc/hosts。然后它开始工作。不知道它是如何工作的。但它解决了我的问题

      【讨论】:

        【解决方案5】:

        我刚刚对 InetAddress 类做了一些实验,还阅读了它的 javadocs。

        在第一次触摸后,我可以告诉我在 2 种情况下得到 UnknownHostException:当我传递非法格式的字符串(如 http://stackoverflow.com 而不是 stackoverflow.com)或当我传递无法在浏览器中解析的 URL 时(比如aosjdfk23423.com)。

        这两种情况都记录在 javadocs 中(尽管在任何地方都没有明确说明对参数格式有任何严格要求)。以下是相关的 javadocs 部分:

        主机名可以是机器名,例如 java.sun.com,或其文本表示 IP地址。如果提供了文字 IP 地址,则只有 检查地址格式的有效性。

        @exception UnknownHostException 如果没有 IP 地址 可以找到host,或者如果指定了 scope_id 用于全球 IPv6 地址。

        总结:

        这行得通:

        InetAddress.getByName("google.com");
        InetAddress.getByName("74.125.87.99");
        

        这会抛出UnknownHostException:

        InetAddress.getByName("http://google.com");
        InetAddress.getByName("unexistingresourse234234.com");
        

        UPD(作为对 cme​​ts 的回答:应该是这样的:

        List<String> hosts = getPossibleHosts(); //these are all hosts you want to transform into inet addresses
        final List<InetAddress> inetAddresses = new LinkedList<InetAddress>();
        final List<String> badHosts = new LinkedList<String>();
        
        for(String host : hosts) {
            try {
                inetAddresses.add(InetAddress.getByName(host));
            } catch (UnknownHostException e) {
                badHosts.add(host);
            }
        }
        

        之后,您可以根据需要处理这两个列表。但是尝试将它们放在同一个列表中是错误的——它们不一样。

        【讨论】:

        • 所以不可能让 getByName 默默接受不存在的域,不是吗?
        • @Basilevs:欢迎来到 Java World!使用 try/catch 块。我建议你阅读一些关于 java 异常的手册。
        • 请在本期中展示如何使用 try/catch,例如 InetAddress ia=InetAddress.getByName("google.invalid"); System.out.println(ia.getHostname());
        • 嗯,这就是重点。如果没有现有的 IP 地址,您将得不到 InetAddress。但这是最初的问题,如果可以在没有主机名解析的情况下获得 InetAddress 对象:`InetAddress 可以表示无法解析的主机名吗?``
        • @Michael Konietzka:你可以在不要求添加代码 sn-p 的情况下对我投反对票。
        猜你喜欢
        • 2017-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 2013-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多