2012-03-29 417 views
78
InetAddress byName = InetAddress.getByName("173.39.161.140"); 
    System.out.println(byName); 
    System.out.println(byName.isReachable(1000)); 

爲什麼isReachable返回false?我可以ping IP。當我可以ping通IP地址時,爲什麼InetAddress.isReachable返回false?

+0

可能重複:http://stackoverflow.com/questions/ 4779367 /問題與難以到達的在inetaddress類 – assylias 2012-03-29 09:32:14

+1

它是相似的。但我找不到解決問題的線索。所以我在這裏重新評估了它。感謝您的提醒! – jiafu 2012-03-29 12:18:37

+1

我會嘗試增加超時。 – jayunit100 2012-04-13 17:01:23

回答

66

「isReachable」方法在很多情況下都不值得使用。您可以滾動到底部,查看我的替代方案,以便簡單測試您是否在線並能夠解析外部主機(即google.com)......通常可以在* NIX機器上工作。

問題

有很多喋喋不休的這個問題:

第1部分:問題

注意,在這種情況下,失敗的重複的例子。

 //also, this fails for an invalid address, like "www.sjdosgoogle.com1234sd" 
     InetAddress[] addresses = InetAddress.getAllByName("www.google.com"); 
     for (InetAddress address : addresses) { 
     if (address.isReachable(10000)) 
     { 
      System.out.println("Connected "+ address); 
     } 
     else 
     { 
      System.out.println("Failed "+address); 
     } 
     } 
      //output:*Failed www.google.com/74.125.227.114* 

第2部分:hackish的解決方法

作爲替代方案,你可以這樣做:

// in case of Linux change the 'n' to 'c' 
    Process p1 = java.lang.Runtime.getRuntime().exec("ping -n 1 www.google.com"); 
    int returnVal = p1.waitFor(); 
    boolean reachable = (returnVal==0); 

的-c選項將允許平簡單地嘗試到達服務器一次(而不是我們以前在終端上使用的無限ping)。

這將返回如果主機可到達。否則,您將得到「2」作爲返回值。

更簡單 - 但當然它是平臺特定的。 使用此命令可能存在某些特權警告 - 但我發現它適用於我的機器。


請注意: 1)該溶液是不生產質量。它有點黑客。如果谷歌關閉,或者你的網絡暫時很慢,或者甚至在你的特權/系統設置中有一些樂趣,如果可能返回錯誤的否定(即使輸入地址可達,它也可能失敗)。 2)isReachable失敗是一個突出的問題。再說一遍 - 有幾個在線資源表明,在寫這篇文章時,由於JVM嘗試訪問主機的方式,沒有「完美」的方式來做這件事 - 我想這是一個固有的平臺特定任務,儘管它很簡單,尚未被JVM充分抽象。

+0

非常感謝你! – jiafu 2012-04-13 23:22:16

+0

@ jayunit100這兩種方法都不工作,'isReachable'我失敗了,使用ping我得到icmp不允許?你知道現在如何處理它嗎? – Yuvi 2013-01-07 08:58:22

+5

@Yuvi如果您使用Windows,則標誌會有所不同。而不是-c你想要-n。 – 2013-10-21 22:31:39

7

如果您只想檢查它是否連接到互聯網,請使用此方法,如果連接了互聯網,它將返回true,如果您使用通過程序嘗試連接的站點的地址,則它更可取。

 public static boolean isInternetReachable() 
    { 
     try { 
      //make a URL to a known source 
      URL url = new URL("http://www.google.com"); 

      //open a connection to that source 
      HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection(); 

      //trying to retrieve data from the source. If there 
      //is no connection, this line will fail 
      Object objData = urlConnect.getContent(); 

     } catch (Exception e) {    
      e.printStackTrace(); 
      return false; 
     } 

     return true; 
    } 
+1

如果服務器沒有web服務器,這是沒有規定的條件在這個問題上。 – 2014-12-04 14:14:25

2

只是明確提到它,因爲其他答案沒有。 isReachable()的ping部分在Unix上需要root訪問權限。正如4779367中的bestss所指出的那樣:

如果你問爲什麼從bash中ping不出來,實際上它確實也需要。做那個ls -l/bin/ping。

由於使用根源是不是在我的情況選擇解決辦法是允許訪問端口7防火牆到特定服務器我感興趣的

-1

既然可以ping計算機,您的Java過程應以足夠的權限運行以執行檢查。可能由於使用較低範圍的端口。如果你用sudo/superuser運行你的java程序,我敢打賭它的工作原理。

+0

您不需要特權* *連接*到低範圍的端口。 – EJP 2015-06-03 06:03:48

0

我建議測試互聯網連接的唯一可靠方法是實際連接並下載文件,或通過exec()解析OS ping調用的輸出。你不能依靠ping的退出代碼,isReachable()是廢話。

如果ping命令正確執行,則不能依賴ping退出代碼,因爲它返回0。不幸的是,如果ping無法到達目標主機,但是從家庭ADSL路由器獲取「目標主機不可達」,ping將正確執行。這是一種被視爲成功命中的回覆,因此退出代碼= 0.必須添加,但這是在Windows系統上。未檢查* nixes。

30

我來這裏是爲了得到同樣問題的答案,但我對任何答案都不滿意,因爲我在尋找一個獨立於平臺的解決方案。這裏是我編寫的代碼,與平臺無關,但需要關於另一臺機器上的任何開放端口的信息(我們大部分時間都是這樣)。

private static boolean isReachable(String addr, int openPort, int timeOutMillis) { 
    // Any Open port on other machine 
    // openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc. 
    try { 
     try (Socket soc = new Socket()) { 
      soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis); 
     } 
     return true; 
    } catch (IOException ex) { 
     return false; 
    } 
} 
+1

謝謝,這是工作! – Butsaty 2015-12-25 05:25:35

+2

這是一個很好的平臺獨立解決方案,謝謝! – ivandov 2016-02-17 19:02:21

+1

我很高興我在這裏結束了,很好的思考Sourabh :) – OmarBizreh 2016-03-12 20:43:48

1

我不知道是什麼時候了原來的問題被要求回到2012年

目前的情況是,中國平安將作爲根被執行的狀態。通過ping可執行文件的授權,您將看到+ s標誌以及屬於root的進程,這意味着它將以root身份運行。運行ls -liat在ping的位置,你應該看到它。

因此,如果您以超級用戶身份運行InetAddress.getByName(「www.google.com」)。isReacheable(5000),它應該返回true。

你需要的原始套接字,它使用ICMP(ping所使用的協議)

InetAddress.getByName是平安可靠適當的授權,但你需要在過程中適當的權限運行它正常。

0
private boolean isReachable(int nping, int wping, String ipping) throws Exception { 

    int nReceived = 0; 
    int nLost = 0; 

    Runtime runtime = Runtime.getRuntime(); 
    Process process = runtime.exec("ping -n " + nping + " -w " + wping + " " + ipping); 
    Scanner scanner = new Scanner(process.getInputStream()); 
    process.waitFor(); 
    ArrayList<String> strings = new ArrayList<>(); 
    String data = ""; 
    // 
    while (scanner.hasNextLine()) { 
     String string = scanner.nextLine(); 
     data = data + string + "\n"; 
     strings.add(string); 
    } 

    if (data.contains("IP address must be specified.") 
      || (data.contains("Ping request could not find host " + ipping + ".") 
      || data.contains("Please check the name and try again."))) { 
     throw new Exception(data); 
    } else if (nping > strings.size()) { 
     throw new Exception(data); 
    } 

    int index = 2; 

    for (int i = index; i < nping + index; i++) { 
     String string = strings.get(i); 
     if (string.contains("Destination host unreachable.")) { 
      nLost++; 
     } else if (string.contains("Request timed out.")) { 
      nLost++; 
     } else if (string.contains("bytes") && string.contains("time") && string.contains("TTL")) { 
      nReceived++; 
     } else { 
     } 
    } 

    return nReceived > 0; 
} 

nping是嘗試ping IP(數據包)的數量,如果你有繁忙的網絡或系統選擇比格爾nping號碼。
wping是時候從IP等待乒乓球,你可以將它設置2000毫秒
使用這種方法ü可以這樣寫:

isReachable(5, 2000, "192.168.7.93"); 
相關問題