簡體   English   中英

如果通過Java中的DNS無法解析,如何獲取本地主機名?

[英]How do I get the local hostname if unresolvable through DNS in Java?

這聽起來像以前應該問過的東西,它有一些,但我希望獲得機器的本地主機名和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文件不包含主機名。 但它確實知道它的主機名,所以我不知道為什么我不能在沒有拋出異常的情況下得到它。

是的,在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()一樣簡單。

如果沒有配置DNS,或者相應的C函數將會讀取/ etc / hosts文件。

如果您獲得127.0.0.1作為IP地址,則可能需要找到特定於操作系統的主機文件,並在其中添加映射到主機名。

這有點像黑客。 但您可以從Java啟動新進程並運行hostname命令。 讀取子進程的輸出流將為您提供localhost的名稱。

在Linux上閱讀

/proc/sys/kernel/hostname

如果你不反對使用maven central的外部依賴,我寫了gethostname4j來解決這個問題。 它只是使用JNA調用libc的gethostname函數(或在Windows上獲取ComputerName)並將其作為字符串返回給您。

https://github.com/mattsheppard/gethostname4j

(我認為這幾乎正是@ danny-thomas所提議的,但如果你已經在使用Maven,可能會更方便;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM