如果通过Java中的DNS无法解析,如何获取本地主机名?

这听起来像之前应该被问过的东西,它有一些,但我希望得到一台机器的本地主机名和IP地址,即使它无法通过DNS解析(在Java中)。

通过迭代NetworkInterfaces.getNetworkInterfaces()我可以获得没有解决方案的本地IP地址。

我发现这个问题的任何答案表明使用getLocalHost()

 InetAddress localhost = java.net.InetAddress.getLocalHost(); hostName = localhost.getHostName(); 

但如果主机名无法通过DNS解析,则会抛出UnknownHostException

如果没有在幕后进行DNS查找,是否无法获取本地主机名?

编辑:检索到的IP地址是10.4.168.23例外是java.net.UnknownHostException: cms1.companyname.com: cms1.companyname.com (主机名已更改为伪匿名),hosts文件不包含主机名。 但它确实知道它的主机名,所以我不确定为什么我不能在没有抛出exception的情况下得到它。

是的,在Java中应该有一种方法来获取主机名而不需要使用名称服务查找,但遗憾的是没有。

但是,你可以这样做:

 if (System.getProperty("os.name").startsWith("Windows")) { // Windows will always set the 'COMPUTERNAME' variable return System.getenv("COMPUTERNAME"); } else { // If it is not Windows then it is most likely a Unix-like operating system // such as Solaris, AIX, HP-UX, Linux or MacOS. // Most modern shells (such as Bash or derivatives) sets the // HOSTNAME variable so lets try that first. String hostname = System.getenv("HOSTNAME"); if (hostname != null) { return hostname; } else { // If the above returns null *and* the OS is Unix-like // then you can try an exec() and read the output from the // 'hostname' command which exist on all types of Unix/Linux. // If you are an OS other than Unix/Linux then you would have // to do something else. For example on OpenVMS you would find // it like this from the shell: F$GETSYI("NODENAME") // which you would probably also have to find from within Java // via an exec() call. // If you are on zOS then who knows ?? // etc, etc } } 

这将使您在传统的Sun JDK平台(Windows,Solaris,Linux)上获得100%的所需,但如果您的操作系统更加激动(从Java角度来看),则会变得不那么容易。 请参阅代码示例中的注释。

我希望有更好的方法。

这个问题已经过时了,但不幸的是仍然具有相关性,因为在Java中获取机器的主机名仍然不是一件容易的事。 这是我在不同系统上进行一些测试运行的解决方案:

 public static void main(String[] args) throws IOException { String OS = System.getProperty("os.name").toLowerCase(); if (OS.indexOf("win") >= 0) { System.out.println("Windows computer name throguh env:\"" + System.getenv("COMPUTERNAME") + "\""); System.out.println("Windows computer name through exec:\"" + execReadToString("hostname") + "\""); } else { if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0) { System.out.println("Linux computer name throguh env:\"" + System.getenv("HOSTNAME") + "\""); System.out.println("Linux computer name through exec:\"" + execReadToString("hostname") + "\""); System.out.println("Linux computer name through /etc/hostname:\"" + execReadToString("cat /etc/hostname") + "\""); } } } public static String execReadToString(String execCommand) throws IOException { Process proc = Runtime.getRuntime().exec(execCommand); try (InputStream stream = proc.getInputStream()) { try (Scanner s = new Scanner(stream).useDelimiter("\\A")) { return s.hasNext() ? s.next() : ""; } } } 

不同操作系统的结果:

OpenSuse 13.1

 Linux computer name throguh env:"machinename" Linux computer name through exec:"machinename " Linux computer name through /etc/hostname:"" 

Ubuntu 14.04 LTS这个有点奇怪,因为echo $HOSTNAME返回正确的主机名,但System.getenv("HOSTNAME")没有(这可能只是我环境的一个问题):

 Linux computer name throguh env:"null" Linux computer name through exec:"machinename " Linux computer name through /etc/hostname:"machinename " 

Windows 7的

 Windows computer name throguh env:"MACHINENAME" Windows computer name through exec:"machinename " 

机器名称已被替换为(某些)匿名化,但我保留了大写和结构。 注意执行hostname时的额外换行符,在某些情况下可能需要考虑它。

或者,使用JNA在unixes上调用gethostname函数,避免反向DNS查找。

一些注意事项:在Linux上,我认为gethostname只是调用uname并解析输出。 在OS X上,情况更复杂,因为您的主机名可能会受到DNS的影响,但除了这些副作用之外,它绝对是我从hostname获得的。

 import com.sun.jna.LastErrorException import com.sun.jna.Library import com.sun.jna.Native ... private static final C c = (C) Native.loadLibrary("c", C.class); private static interface C extends Library { public int gethostname(byte[] name, int size_t) throws LastErrorException; } public String getHostName() { byte[] hostname = new byte[256]; c.gethostname(hostname, hostname.length) return Native.toString(hostname) } 

jna-platform.jar包含Win32函数,所以它就像调用Kernel32Util.getComputerName()一样简单。

如果您获得127.0.0.1作为IP地址,则可能需要找到特定于操作系统的主机文件,并在其中添加映射到主机名。

这有点像黑客。 但您可以从Java启动新进程并运行hostname命令。 读取子进程的输出流将为您提供localhost的名称。

如果没有配置DNS,Java将读取/ etc / hosts文件,或者相应的C函数将读取。

在Linux上阅读

 /proc/sys/kernel/hostname 

如果你不反对使用maven central的外部依赖,我写了gethostname4j来解决这个问题。 它只是使用JNA调用libc的gethostname函数(或在Windows上获取ComputerName)并将其作为字符串返回给您。

https://github.com/mattsheppard/gethostname4j

(我认为这几乎就是@ danny-thomas提出的建议,但如果你已经在使用Maven,可能会更方便;)