下面哪一种方法是在Java中获得当前计算机主机名的最佳和最可移植的方法?

Runtime.getRuntime().exec(“hostname”)

vs

InetAddress.getLocalHost().getHostName()


当前回答

基于Dan Ortega的回答,我创建了一个通用的executeCommand(String)方法,它接受命令作为参数。

import java.io.*;

public class SystemUtil {
  public static void main(String[] args) throws IOException {
    System.out.println(retrieveHostName());
  }
     
  public static String retrieveHostName() throws IOException {
    return executeCommand("hostname");
  }
     
  private static String executeCommand(String command) throws IOException {
    return new BufferedReader(
        new InputStreamReader(Runtime.getRuntime().exec(command).getInputStream()))
      .readLine();
  }
}

其他回答

InetAddress.getLocalHost(). gethostname()是更可移植的方式。

Exec(“hostname”)实际上调用操作系统来执行hostname命令。

以下是关于SO的一些其他相关答案:

Java当前机器名和登录用户? 获取本地机器的DNS名称,就像远程机器看到的那样

编辑:你应该看看A.H.的回答,或者Arnout Engelen的回答,详细说明为什么这可能不会像预期的那样工作,这取决于你的情况。作为对这个特别要求可移植的人的回答,我仍然认为getHostName()很好,但它们提出了一些值得考虑的优点。

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

https://github.com/mattsheppard/gethostname4j

基于Dan Ortega的回答,我创建了一个通用的executeCommand(String)方法,它接受命令作为参数。

import java.io.*;

public class SystemUtil {
  public static void main(String[] args) throws IOException {
    System.out.println(retrieveHostName());
  }
     
  public static String retrieveHostName() throws IOException {
    return executeCommand("hostname");
  }
     
  private static String executeCommand(String command) throws IOException {
    return new BufferedReader(
        new InputStreamReader(Runtime.getRuntime().exec(command).getInputStream()))
      .readLine();
  }
}

严格地说,在Unix上,你没有选择,只能调用hostname(1)或- gethostname(2)。这是你电脑的名字。任何试图通过IP地址确定主机名的尝试,就像这样

InetAddress.getLocalHost().getHostName()

在某些情况下一定会失败:

The IP address might not resolve into any name. Bad DNS setup, bad system setup or bad provider setup may be the reason for this. A name in DNS can have many aliases called CNAMEs. These can only be resolved in one direction properly: name to address. The reverse direction is ambiguous. Which one is the "official" name? A host can have many different IP addresses - and each address can have many different names. Two common cases are: One ethernet port has several "logical" IP addresses or the computer has several ethernet ports. It is configurable whether they share an IP or have different IPs. This is called "multihomed". One Name in DNS can resolve to several IP Addresses. And not all of those addresses must be located on the same computer! (Usecase: A simple form of load-balancing) Let's not even start talking about dynamic IP addresses.

另外,不要将ip地址的名称与主机的名称(hostname)混淆。打个比方可能会更清楚:

There is a large city (server) called "London". Inside the city walls much business happens. The city has several gates (IP addresses). Each gate has a name ("North Gate", "River Gate", "Southampton Gate"...) but the name of the gate is not the name of the city. Also you cannot deduce the name of the city by using the name of a gate - "North Gate" would catch half of the bigger cities and not just one city. However - a stranger (IP packet) walks along the river and asks a local: "I have a strange address: 'Rivergate, second left, third house'. Can you help me?" The local says: "Of course, you are on the right road, simply go ahead and you will arrive at your destination within half an hour."

我认为这很好地说明了这一点。

好消息是:真实的主机名通常是不必要的。在大多数情况下,这台主机上任何解析为IP地址的名称都可以。(陌生人可能会从北门(Northgate)进入城市,但乐于助人的当地人会翻译“左边第二个”部分。)

在其余的情况下,您必须使用该配置设置的最终来源-这是C函数gethostname(2)。该函数也由程序主机名调用。

只有一句话……跨平台(Windows-Linux-Unix-Mac(Unix))[始终工作,不需要DNS]:

String hostname = new BufferedReader(
    new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))
   .readLine();

你完蛋了!!