2011-05-18 39 views
13

Điều này nghe giống như một cái gì đó đáng lẽ phải được hỏi trước đây, và nó có kiểu, nhưng tôi đang tìm địa chỉ IP và máy chủ cục bộ của máy ngay cả khi nó không thể phân giải được thông qua DNS (trong Java).Làm cách nào để nhận tên máy chủ cục bộ nếu không thể giải quyết thông qua DNS trong Java?

Tôi có thể nhận địa chỉ IP cục bộ mà không cần giải quyết bằng cách lặp lại qua NetworkInterfaces.getNetworkInterfaces().

Bất kỳ câu trả lời cho câu hỏi này tôi đã tìm thấy chỉ sử dụng getLocalHost()

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

nhưng điều này ném một UnknownHostException nếu hostname không được giải quyết thông qua DNS.

Không có cách nào để nhận tên máy chủ cục bộ mà không có tra cứu DNS xảy ra sau hậu trường?

chỉnh sửa: địa chỉ IP lấy ra là 10.4.168.23 Trường hợp ngoại lệ là java.net.UnknownHostException: cms1.companyname.com: cms1.companyname.com (hostname thay đổi cho giả giấu tên), và các tập tin host không chứa tên máy. Nhưng nó biết tên máy chủ của nó, vì vậy tôi không chắc chắn lý do tại sao tôi không thể nhận được nó mà không có ngoại lệ bị ném.

Trả lời

1

Nếu bạn nhận 127.0.0.1 làm địa chỉ IP thì bạn có thể cần phải định vị tệp máy chủ cụ thể và thêm ánh xạ vào tên máy chủ trong đó.

+0

Hệ điều hành biết tên máy, như khi tôi gọi getLocalHost (), nó ném một ngoại lệ có chứa tên máy chủ. Tôi chỉ muốn có thể nhận được tên máy chủ đó mà không cần tra cứu. –

+0

Đảm bảo rằng tên máy chủ của bạn không chứa bất kỳ ký tự gạch dưới nào. Nếu bạn đang ở trên Windows thì nó sẽ không ngăn cản bạn sử dụng dấu gạch dưới trong tên máy, nhưng nó không hoạt động với Java vì kiểm tra nghiêm ngặt các ký tự được cho phép. – sinha

1

Đây là một chút hack. Nhưng bạn có thể khởi chạy một Quy trình mới từ Java và chạy lệnh hostname. Đọc đầu ra của tiến trình con sẽ cho bạn tên của localhost.

+0

Tôi nghĩ về điều này là tốt, nhưng đã hy vọng cho một giải pháp tốt hơn. –

11

Có, có nên là một cách trong Java để nhận tên máy chủ mà không cần phải đặt tên cho tra cứu dịch vụ nhưng rất tiếc là không có.

Tuy nhiên, bạn có thể làm một cái gì đó như thế này:

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 
    } 
} 

và điều đó sẽ giúp bạn có được 100% những gì bạn muốn trên các nền tảng Sun JDK truyền thống (Windows, Solaris, Linux) nhưng trở nên ít dễ dàng nếu hệ điều hành của bạn là nhiều excotic (từ một phối cảnh Java). Xem các bình luận trong ví dụ mã.

Tôi ước có một cách tốt hơn.

+0

Tôi không nhận được 'HOSTNAME' khi Tomcat là một dịch vụ rc.d trong FreeBSD, thật không may. – lapo

+0

@lapo. Không phải là một vấn đề Java. Bạn sẽ cần phải hiểu shell của bạn: khi nào biến môi trường 'HOSTNAME' được đặt? Bạn có thể sẽ nhận được một câu trả lời hay nếu bạn hỏi trong một diễn đàn Unix/Linux một cái gì đó như: * "Biến môi trường HOSTNAME không được định nghĩa. Tại sao?" *. – peterh

+0

không phải là một vấn đề Java, nhưng có sẵn theo mặc định là một điều; nếu tôi phải thay đổi mặc định hệ thống, tôi cũng có thể xác định đúng trong '127.0.0.1' trong'/etc/host' (đó là một quy tắc tốt anyways). Cuối cùng, tôi đã sử dụng 'HOSTNAME' khác' COMUTERNAME' khác 'getLocalHost()'. – lapo

1

Java sẽ đọc tệp/etc/hosts nếu không có cấu hình DNS, hoặc đúng hơn là các hàm C tương ứng sẽ.

5

Câu hỏi này cũ, nhưng tiếc là vẫn còn có liên quan vì nó vẫn không tầm thường để có được tên máy chủ của máy trong Java. Đây là giải pháp của tôi với một số thử nghiệm chạy trên các hệ thống khác nhau:

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() : ""; 
      } 
     } 
    } 

Kết quả cho hệ điều hành khác nhau:

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 Cái này là kinda lạ kể từ echo $HOSTNAME trả về tên máy chính xác, nhưng System.getenv("HOSTNAME") không (điều này tuy nhiên có thể là một vấn đề với chỉ môi trường của tôi):

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

của Windows 7

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

Tên máy đã được thay thế cho (một số) ẩn danh, nhưng tôi đã giữ nguyên cách viết hoa và cấu trúc. Lưu ý dòng mới bổ sung khi thực hiện hostname, bạn có thể phải tính đến nó trong một số trường hợp.

+0

Tôi thấy cùng một vấn đề trên Ubuntu 14.04 với biến môi trường 'HOSTNAME'. Nó không được xuất ra các nhiệm vụ được khởi chạy bởi shell (bash). Việc thực thi 'export HOSTNAME' sẽ giải quyết được vấn đề. – neuhaus

2

Hoặc, sử dụng JNA để gọi hàm gethostname trên các bản sao lưu, tránh tra cứu DNS ngược.

Một số lưu ý: trên Linux, tôi tin rằng gethostname chỉ cần gọi uname và phân tích cú pháp đầu ra. Trên OS X tình hình phức tạp hơn, vì tên máy chủ của bạn có thể bị ảnh hưởng bởi DNS, nhưng những tác dụng phụ này sang một bên, nó chắc chắn là những gì tôi nhận được từ 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 bao gồm các chức năng Win32, do đó nó đơn giản như một cuộc gọi đến Kernel32Util.getComputerName().

+0

Câu trả lời hay hơn vì nó không phụ thuộc vào DNS. – jkschneider

0

trên Linux đọc

/proc/sys/kernel/hostname 
0

Nếu bạn không chống lại việc sử dụng một sự phụ thuộc bên ngoài từ maven trung ương, tôi đã viết gethostname4j để giải quyết vấn đề này cho bản thân mình. Nó chỉ sử dụng JNA để gọi hàm gethostname của libc (hoặc lấy ComputerName trên Windows) và trả về cho bạn dưới dạng một chuỗi.

https://github.com/mattsheppard/gethostname4j

(Tôi nghĩ đó là gần như chính xác những gì @ danny-thomas đề xuất, nhưng có lẽ thuận tiện hơn nếu bạn đã sử dụng Maven;)

Các vấn đề liên quan