InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Dlaczego isReachable
wraca false
? Mogę pingować adres IP.
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Dlaczego isReachable
wraca false
? Mogę pingować adres IP.
Odpowiedzi:
W wielu przypadkach metoda „isReachable” nie była warta zastosowania. Możesz przewinąć w dół, aby zobaczyć moją alternatywę dla prostego testowania, jeśli jesteś online i jesteś w stanie rozwiązać zewnętrzne hosty (np. Google.com) ... Co ogólnie wydaje się działać na maszynach * NIX.
Problem
Jest dużo gadania na ten temat:
Oto inne, podobne pytania:
A nawet zgłoszony błąd w tej samej sprawie:
Część 1: Odtwarzalny przykład problemu
Zauważ, że w tym przypadku nie powiedzie się.
//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*
Część 2: Obejście problemu hakerskiego
Alternatywnie możesz to zrobić:
// 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);
Opcja -c polecenia ping pozwoli pingowi po prostu raz spróbować dotrzeć do serwera (w przeciwieństwie do nieskończonego polecenia ping, którego używamy na terminalu).
Zwróci to 0, jeśli host jest osiągalny . W przeciwnym razie zwrócona zostanie wartość „2”.
O wiele prostsze - ale oczywiście zależy to od platformy. Mogą istnieć pewne zastrzeżenia dotyczące uprawnień do używania tego polecenia - ale uważam, że działa na moich komputerach.
NALEŻY pamiętać, że: 1) To rozwiązanie nie jest jakością produkcji. To trochę hack. Jeśli Google nie działa lub Twój internet jest chwilowo wolny, a może nawet jeśli w Twoich uprawnieniach / ustawieniach systemu jest coś dziwnego, może zwrócić fałszywe negatywy (tj. Może się nie powieść, nawet jeśli adres wejściowy jest osiągalny). 2) Awaria isReachable jest nierozstrzygniętym problemem. Ponownie - istnieje kilka zasobów internetowych wskazujących, że w chwili pisania tego tekstu nie ma „idealnego” sposobu na zrobienie tego, ze względu na sposób, w jaki JVM próbuje dotrzeć do hostów - wydaje mi się, że jest to z natury zadanie specyficzne dla platformy, które chociaż proste , nie został jeszcze wystarczająco wyodrębniony przez JVM.
isReachable
niepowodzenia i użycia polecenia ping otrzymuję niedozwolone ICMP? Czy już wiesz, jak sobie z tym poradzić?
public boolean waitFor(long timeout, TimeUnit unit)
w java.lang.Process (@since 1.8)
Przyszedłem tutaj, aby uzyskać odpowiedź na to samo pytanie, ale żadna z nich nie była satysfakcjonująca, ponieważ szukałem rozwiązania niezależnego od platformy. Oto kod, który napisałem i jest niezależny od platformy, ale wymaga informacji o dowolnym otwartym porcie na innym komputerze (który mamy przez większość czasu).
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;
}
}
InetAddress.isReachable()
już robi, przez port 7, z tym wyjątkiem, że ten ostatni jest bardziej inteligentny w kwestii tego, co różne możliwe IOExceptions
oznaczają pod względem osiągalności.
InetAddress.isReachable()
został przeciążony, aby dołączyć argument portu do standardowej biblioteki. Zastanawiam się, dlaczego nie został uwzględniony?
Jeśli chcesz tylko sprawdzić, czy jest podłączony do Internetu, użyj tej metody. Zwraca wartość true, jeśli internet jest podłączony. Najlepiej, jeśli używasz adresu witryny, z którą próbujesz się połączyć za pośrednictwem programu.
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;
}
Wspominam o tym wyraźnie, ponieważ inne odpowiedzi nie. Część isReachable () zawierająca ping wymaga uprawnień administratora w systemie Unix. I jak wskazał bestsss w 4779367 :
A jeśli zapytasz, dlaczego ping z basha nie, w rzeczywistości też potrzebuje. Zrób to ls -l / bin / ping.
Ponieważ użycie roota nie wchodziło w grę w moim przypadku, rozwiązaniem było zezwolenie na dostęp do portu 7 w firewallu do konkretnego serwera, który mnie interesował.
Nie jestem pewien, jaki był stan, gdy zadawano pierwotne pytanie w 2012 roku.
W obecnej formie ping zostanie wykonany jako root. Po autoryzacji pliku wykonywalnego ping zobaczysz flagę + s i proces należący do roota, co oznacza, że będzie działał jako root. uruchom ls -liat na miejscu, w którym znajduje się ping i powinieneś go zobaczyć.
Tak więc, jeśli uruchomisz InetAddress.getByName („www.google.com”). IsReacheable (5000) jako root, powinno zwrócić wartość true.
potrzebujesz odpowiednich uprawnień do gniazda raw, z którego korzysta ICMP (protokół używany przez ping)
InetAddress.getByName jest równie niezawodny jak ping, ale potrzebujesz odpowiednich uprawnień do procesu, aby działał poprawnie.
Sugerowałbym, że JEDYNYM niezawodnym sposobem przetestowania połączenia internetowego jest faktyczne połączenie I pobranie pliku LUB przeanalizowanie danych wyjściowych wywołania ping systemu operacyjnego za pośrednictwem exec (). Nie możesz polegać na kodzie zakończenia dla polecenia ping, a isReachable () to bzdura.
Nie można polegać na kodzie zakończenia polecenia ping, ponieważ zwraca on 0, jeśli polecenie ping zostanie wykonane poprawnie. Niestety, polecenie ping jest wykonywane poprawnie, jeśli nie może dotrzeć do hosta docelowego, ale otrzyma komunikat „Host docelowy nieosiągalny” z domowego routera ADSL. Jest to rodzaj odpowiedzi, która jest traktowana jako udane trafienie, więc kod zakończenia = 0. Muszę jednak dodać, że jest to system Windows. Niezaznaczone * nixes.
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 to liczba prób pingowania ip (pakietów), jeśli masz zajętą sieć lub systemy, wybierz większe numery nping.
wping to czas oczekiwania na pong z ip, możesz ustawić go na 2000ms,
aby użyć tej metody, możesz napisać to:
isReachable(5, 2000, "192.168.7.93");
Lub używając w ten sposób:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
jest flappy i czasami zwraca nieosiągalny dla adresów, które możemy pingować.
Wypróbowałem następujące:
ping -c 1 <fqdn>
i sprawdź exit status
.
Działa we wszystkich przypadkach, które wypróbowałem, gdzie InetAddress.isReachable
nie działa.
Ponieważ można pingować komputer, proces Java powinien działać z uprawnieniami wystarczającymi do wykonania sprawdzenia. Prawdopodobnie z powodu wykorzystania portów z dolnego zakresu. Jeśli uruchomisz program java z sudo / superuser, założę się, że działa.