ICMP differs from transport protocols such as TCP and UDP in that it is not typically used to exchange data between systems. This Java Program pings an IP address in Java using InetAddress class. It is successful in case of Local Host but for other hosts this program shows that the host is unreachable.
For example in main, if I pass these parameters to pingHost : pingComputer. pingHost("ROOM-1234"); It pings fine and returns correct host name/address.
isReachable()
will use ICMP ECHO REQUEST
s if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.
Thus your problem is probably a configuration issue of not enough permissions to do this on the client machine or a port 7 issue on the server if your client doesn't have permission to do the ICMP ECHO REQUEST
. Probably both in your case, you need to resolve one side or the other to get this to work.
I tested the following on OSX and Linux clients and it works when testing for reachablity of other OSX, Linux and Windows Server machines. I don't have a Windows machine to run this as a client.
import java.io.IOException;
import java.net.InetAddress;
public class IsReachable
{
public static void main(final String[] args) throws IOException
{
final InetAddress host = InetAddress.getByName(args[0]);
System.out.println("host.isReachable(1000) = " + host.isReachable(1000));
}
}
from what I read here. It is apparently a Windows limitation and ICMP PING
isn't supported on Windows as a system call previous to Windows 2000, so it defaults to try and connect to Port 7 and that is blocked on the machine you are trying to "reach". Java doesn't support the new native system call yet. The permissions thing is for Unix based system as they require root to send ICMP
packets.
If you want to roll your own Windows native JNI ICMP PING
for Windows 2000 and newer there is the IcmpSendEcho Function.
I use this function (from this article) when I need a real ICMP ping in Windows, Linux and OSX (I have not tested other systems).
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch( Exception e ) {
e.printStackTrace();
return false;
}
}
A bit late, but I stumbled upon this while trying to do the same thing.
One workaround that worked for me and which I used was to just use the command line ping directly.
public static boolean ping(String host)
{
boolean isReachable = false;
try {
Process proc = new ProcessBuilder("ping", host).start();
int exitValue = proc.waitFor();
System.out.println("Exit Value:" + exitValue);
if(exitValue == 0)
isReachable = true;
} catch (IOException e1) {
System.out.println(e1.getMessage());
e1.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return isReachable;
}
One of the reasons is that the timeout you've specified is too low. I had a similar problem but when i increased the timeout to an appropriate value, the isReachable invocation returned a correct value.
I saw a lot of bad code written related to that issue. The code that worked for my is (site do not know to correctly parse my code file) :
public class Test {
public static boolean isReachablebyPing(String ip) {
try {
String command;
if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
// For Windows
command = "ping -n 2 " + ip;
} else {
// For Linux and OSX
command = "ping -c 2 " + ip;
}
Process proc = Runtime.getRuntime().exec(command);
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
outputGobbler.start();
proc.waitFor();
return checkAvailability(outputGobbler.getOutputLines());
} catch(IOException | InterruptedException ex) {
Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
public static void main(String... args) {
String ip = "10.20.20.17"; // false in my case
String ip1 = "10.20.20.100"; // true in my case
System.out.println(ip + " is avalaible " + isReachablebyPing(ip));
System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1));
}
private static boolean checkAvailability(List<String> outputLines) {
for(String line : outputLines) {
if(line.contains("unreachable")) {
return false;
}
if(line.contains("TTL=")) {
return true;
}
}
return false;
}
}
class StreamGobbler extends Thread {
protected InputStream is;
protected String type;
protected List<String> outputLines;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
outputLines = new ArrayList<>();
}
public List<String> getOutputLines() {
return outputLines;
}
@Override
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null) {
outputLines.add(line);
}
} catch(IOException ex) {
Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With