2013-05-17 183 views
3

中我有一个要求,其中一个IP地址可以被映射到它的多个主机名。我试图调查InetAddress.getAllByName("10.33.28.55")但是我没有得到期望的结果,它只返回一个条目。对IP地址nslookup返回所有DNS条目。如何在Java中检索与此IP地址关联的所有主机名?获取IP地址的所有主机名的网络

+0

你运行'nslook在与您的Java代码相同的机器上启动? 'InetAddress.getAllByName()'*应该*做你所问的。 –

+0

@BrianRoach:最初我没有,但是,当我跑'InetAddress.getAllByName()'在同一台机器上'nslookup'它仍然返回数组中的1项,我期待2.有趣的是,'getCanonicalHostName( )'和'getHostName()'函数返回了2个不同的值。我期待这两个值会出现在数组中的2个元素不同。 – devang

+2

其实......看着'InetAddress.getAllByName()'的来源......如果它是一个IP地址,它实际上并没有进行查找,嘿。你找回一个包含你提供的IP的'InetAddress'对象。每天学些新东西;我不认为我曾经尝试过。 –

回答

4

在为InetAddress.getAllByName()的源代码看你会发现它实际上并没有做DNS查询如果提供的String是IP地址的文本表示。它只是返回一个数组,其中包含一个包含IP的单个InetAdddress对象。他们甚至提出一个方便的评论权的方法:

// if host is an IP address, we won't do further lookup 

(参见:http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java.net/InetAddress.java.html

如果只有JavaDoc中是如此清晰。它声明“如果提供了文字IP地址,则只检查地址格式的有效性。” ...我会争辩说,不会告诉你,它不会被抬头。

想一想吧,但是......它在InetAddress的上下文中有意义 - 该类封装了一个IP地址,您只有一个IP地址。它真的需要getHostNames()getAllCanonicalNames()(注意多个)方法,可以做你正在问的东西。我正在考虑打开一个问题/提交补丁。

这就是说,它会出现目前有在做,其中多个PTR记录支持RDNS查询的方法没有建立。所有其他查找方法只是删除返回的第一条记录,这就是你得到的。

你将不得不考虑对Java的第三方DNS库(对不起,我没有使用任何他们的经验)。

修改添加:我喜欢搞清楚事情。我没有一个具有多个PTR记录的IP方便测试,但它应该做的伎俩。

import java.io.IOException; 
import java.util.Properties; 
import javax.naming.Context; 
import javax.naming.NamingException; 
import javax.naming.directory.Attribute; 
import javax.naming.directory.Attributes; 
import javax.naming.directory.InitialDirContext; 

public class App 
{ 
    public static void main(String[] args) throws IOException, NamingException 
    { 
     Properties env = new Properties(); 
     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory"); 
     InitialDirContext idc = new InitialDirContext(env); 

     String ipAddr = "74.125.225.196"; 

     // Turn the IP into an in-addr.arpa name 
     // 196.225.125.74.in-addr.arpa. 
     String[] quads = ipAddr.split("\\."); 
     StringBuilder sb = new StringBuilder(); 
     for (int i = quads.length - 1; i >= 0; i--) 
     { 
      sb.append(quads[i]).append("."); 
     } 
     sb.append("in-addr.arpa."); 
     ipAddr = sb.toString(); 

     Attributes attrs = idc.getAttributes(ipAddr, new String[] {"PTR"}); 
     Attribute attr = attrs.get("PTR"); 

     if (attr != null) 
     { 
      for (int i = 0; i < attr.size(); i++) 
      { 
       System.out.println((String)attr.get(i)); 
      } 
     } 
    } 
} 
+0

那真是太棒了。但是,我回到创建一个小脚本来为我做这些东西。非常感谢。 – devang

+0

也许你可以通过JNDI进行反向查找。 – EJP

+0

非常好,但我认为你可以承认使用JNDI的想法的来源。 – EJP

0

嘛,只有一个好办法:拨打NSLOOKUP或挖或任何从Java进程。

随着调用Runtime.getRuntime()。EXEC(..)

或更好的ProcessBuilder ...

+0

我意识到这一点,我试图避免这样做,所以我没有做解析并依靠Java返回。看来我将不得不使用这种方法,使用'nslookup'或'host'命令来获取列表并进行必要的解析。 – devang

0

这个答案可能会有所帮助:https://stackoverflow.com/a/24205035/8026752

使用的DNSNameService作品lookupAllHostAddr方法对我来说,和主机名返回的所有IP地址。也许它也有助于通过IP地址查找所有主机名,但似乎这取决于DNS服务器配置。在我的情况下,我甚至找不到使用nslookup的所有主机名,所以我无法测试它,所以我不确定这个解决方案。

一个建议是,lookupAllHostAddr也不是一成不变的方法,所以你应该使用这样的:

InetAddress[] ipAddress = new DNSNameService().lookupAllHostAddr("hostname") 

此外,从我的角度来看,这个环节可能是有趣的(这也是从所提到的相同的答案线程信息通过我上面,我只是总结了一点):

https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html

在链接页面,您可以找到性能禁用查找缓存:

  • sun.net.inetaddr.ttl - 你应该把它添加到JVM启动命令行像这样:-Dsun.net.inetaddr.ttl=0,0这里指主机将被缓存持续10秒
  • networkaddress.cache.ttl - 你应该需要的值添加到位于java.security文件在%JRE%\lib\security

有点更多信息可以在这里也可以找到:

http://www.rgagnon.com/javadetails/java-0445.html