InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Por que isReachable
retorna false
? Posso fazer ping no IP.
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
Por que isReachable
retorna false
? Posso fazer ping no IP.
Respostas:
O método "isReachable" não vale a pena usar para mim em muitos casos. Você pode rolar até a parte inferior para ver minha alternativa para simplesmente testar se você está online e é capaz de resolver hosts externos (por exemplo, google.com) ... O que geralmente parece funcionar em máquinas * NIX.
O problema
Fala-se muito sobre isso:
Aqui estão outras questões semelhantes:
Detectar conexão com a Internet usando Java
Como faço para testar a disponibilidade da internet em Java?
E até mesmo um bug relatado no mesmo assunto:
Parte 1: um exemplo reproduzível do problema
Observe que, neste caso, ele falha.
//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*
Parte 2: Uma Solução Alternativa Hackish
Como alternativa, você pode fazer o seguinte:
// 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);
A opção -c de ping permitirá que o ping simplesmente tente alcançar o servidor uma vez (ao contrário do ping infinito que estamos acostumados a usar no terminal).
Isso retornará 0 se o host estiver acessível . Caso contrário, você obterá "2" como valor de retorno.
Muito mais simples - mas é claro que é específico da plataforma. E pode haver certas advertências de privilégio para usar esse comando - mas acho que funciona em minhas máquinas.
POR FAVOR, observe que: 1) Esta solução não é qualidade de produção. É um pouco hack. Se o Google estiver fora do ar, ou sua internet estiver temporariamente lenta, ou talvez até mesmo se houver alguma graça em seus privilégios / configurações do sistema, ele pode retornar falsos negativos (ou seja, pode falhar mesmo que o endereço de entrada seja acessível). 2) A falha isReachable é um problema pendente. Novamente - existem vários recursos online indicando que não existe uma maneira "perfeita" de fazer isso no momento da redação deste artigo, devido à maneira como a JVM tenta alcançar os hosts - acho que é uma tarefa intrinsecamente específica da plataforma que, embora simples , ainda não foi suficientemente abstraído pela JVM.
isReachable
estou obtendo falha e usando ping estou recebendo icmp não permitido? Você sabe como lidar com isso agora?
public boolean waitFor(long timeout, TimeUnit unit)
em java.lang.Process (@since 1.8)
Vim aqui para obter uma resposta para esta mesma pergunta, mas não fiquei satisfeito com nenhuma das respostas porque estava à procura de uma solução independente de plataforma. Aqui está o código que escrevi e é independente de plataforma, mas requer informações sobre qualquer porta aberta na outra máquina (que temos na maioria das vezes).
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()
já faz, via porta 7, exceto que esta última é mais inteligente sobre o que as várias possíveis IOExceptions
significam em termos de acessibilidade.
InetAddress.isReachable()
fosse sobrecarregado para incluir o argumento da porta, na biblioteca padrão. Eu me pergunto por que não foi incluído?
Se você deseja apenas verificar se ele está conectado à internet use este método, retorna verdadeiro se a internet estiver conectada, é preferível se você usar o endereço do site que está tentando conectar através do programa.
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;
}
Apenas mencionando explicitamente, já que as outras respostas não o fazem. A parte ping de isReachable () requer acesso root no Unix. E como apontado por bestsss em 4779367 :
E se você perguntar por que o ping do bash não funciona, na verdade ele também precisa. Faça isso ls -l / bin / ping.
Como usar root não era uma opção no meu caso, a solução foi permitir o acesso à porta 7 do firewall para o servidor específico no qual eu estava interessado.
Não tenho certeza de qual era o estado quando a pergunta original foi feita em 2012.
Como está agora, o ping será executado como root. Através da autorização do executável ping você verá o sinalizador + s, e o processo pertencente ao root, o que significa que será executado como root. execute ls -liat onde o ping está localizado e você deverá vê-lo.
Portanto, se você executar InetAddress.getByName ("www.google.com"). IsReacheable (5000) como root, ele deve retornar verdadeiro.
você precisa de autorizações adequadas para o soquete bruto, que é usado pelo ICMP (o protocolo usado pelo ping)
InetAddress.getByName é tão confiável quanto o ping, mas você precisa de permissões adequadas no processo para que ele seja executado corretamente.
Eu sugeriria que a ÚNICA maneira confiável de testar uma conexão com a Internet é realmente conectar E baixar um arquivo OU analisar a saída de uma chamada de ping do sistema operacional via exec (). Você não pode confiar no código de saída para ping e isReachable () é uma porcaria.
Você não pode confiar em um código de saída de ping, pois ele retorna 0 se o comando ping for executado corretamente. Infelizmente, o ping é executado corretamente se não puder alcançar o host de destino, mas obtém um "Host de destino inalcançável" de seu roteador ADSL doméstico. Este é o tipo de resposta que é tratada como uma resposta bem-sucedida, portanto, código de saída = 0. Porém, é preciso acrescentar que se trata de um sistema Windows. Não verificado * 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 é o número de tentativas de ping de ip (pacotes), se você tiver uma rede ou sistemas ocupados, escolha números nping maiores.
wping é o tempo de espera pelo pong do ip, você pode configurá-lo
para 2.000 ms para usar este método. Você pode escrever isto:
isReachable(5, 2000, "192.168.7.93");
Ou usando desta forma:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
é flappy, e às vezes retorna inacessível para endereços que podemos pingar.
Tentei o seguinte:
ping -c 1 <fqdn>
e verifique o exit status
.
Funciona para todos os casos que tentei InetAddress.isReachable
e não funciona.
Como você pode executar o ping no computador, seu processo Java deve ser executado com privilégios suficientes para realizar a verificação. Provavelmente devido ao uso de portas na faixa inferior. Se você executar seu programa java com sudo / superuser, aposto que funciona.