如何从Windows进行真正的Java ping?

Ste*_*ins 28 java windows networking ping

我在网络上有一个设备,我试图ping我的Java程序.通过我的Windows命令提示符,我可以ping设备地址,并在地址上做一个tracert罚款.

在线,我已经看到,为了通过Java执行ping操作,您必须执行以下操作:

InetAddress.getByName(address).isReachable(timeout);
Run Code Online (Sandbox Code Playgroud)

但是,当我在我的设备地址上使用此代码时,它总是在我的程序中返回false.我正在使用具有良好超时值的正确IPv4地址.此外,如果我使用本地主机地址,它工作正常.

为什么我可以通过cmd ping设备,但不能通过我的程序?我在各个地方听说这不是真正的 ping.

有没有更好的方法来模拟Java中的ping?

谢谢

小智 27

isReachable()如果可以获得权限,则使用ICMP ECHO REQUESTs ,否则将尝试在目标主机的端口7(Echo)上建立TCP连接. 因此,如果您的客户端没有权限执行此操作,则您的问题可能是在客户端计算机上执行此操作的权限不足或服务器上的端口7问题的配置问题.可能在你的情况下,你需要解决一方或另一方才能使其发挥作用.
ICMP ECHO REQUEST

我在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));
    }
}
Run Code Online (Sandbox Code Playgroud)

从我在这里读到的.它显然是Windows限制,ICMP PING在Windows上不支持作为Windows 2000之前的系统调用,因此它默认尝试连接到端口7,并且在您尝试"到达"的计算机上被阻止.Java尚不支持新的本机系统调用.权限是基于Unix的系统,因为它们需要root才能发送ICMP数据包.

如果要为Windows 2000及更高版本推出自己的Windows本机JNI ICMP PING,则需要使用IcmpSendEcho函数.


Mat*_*son 9

当我在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 唯一的问题是,如果你在Windows上并且在同一个子网中ping某些不可达/超时的东西,你仍然会得到一个退出值为0.所以你需要管它以找到像TTL确认它是否实际可达.`cmd ="ping -n 1"+ host +"| find \"TTL \""`为了使java除了来自windows的管道命令,你必须有一个像这样的命令`cmd ="cmd/c ping - n 1"+ host +"| find \"TTL \""` (2认同)
  • 注意事项:如果在执行Runtime.exec()时没有读取stdout和stderr流,并且应用程序将太多数据写入其中一个流,则会阻塞.你的应用程序和戈多将有一些共同点.我不知道缓冲区大小是什么,我认为它们依赖于操作系统.所以"ping -n 1"可能工作正常,但"ping -n 5"可以无限期挂起. (2认同)