85

我正在使用这部分代码在java中ping一个ip地址,但只有ping localhost是成功的,对于其他主机,程序说主机无法访问。我禁用了我的防火墙,但仍然有这个问题

public static void main(String[] args) throws UnknownHostException, IOException {
    String ipAddress = "127.0.0.1";
    InetAddress inet = InetAddress.getByName(ipAddress);

    System.out.println("Sending Ping Request to " + ipAddress);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");

    ipAddress = "173.194.32.38";
    inet = InetAddress.getByName(ipAddress);

    System.out.println("Sending Ping Request to " + ipAddress);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");
}

输出是:

向 127.0.0.1
主机
发送 Ping 请求可达 向 173.194.32.38
主机发送 Ping 请求不可达

4

16 回答 16

70

InetAddress.isReachable()根据javadoc

“.. 如果可以获得特权,典型的实现将使用 ICMP ECHO REQUEST,否则它将尝试在目标主机的端口 7 (Echo) 上建立 TCP 连接..”。

选项 #1 (ICMP) 通常需要管理(root)权限。

于 2012-07-16T16:16:38.283 回答
38

我认为这段代码会帮助你:

public class PingExample {
    public static void main(String[] args){
        try{
            InetAddress address = InetAddress.getByName("192.168.1.103");
            boolean reachable = address.isReachable(10000);

            System.out.println("Is host reachable? " + reachable);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
于 2015-04-05T18:26:58.717 回答
20

检查您的连接性。在我的电脑上,这两个 IP 都打印了 REACHABLE:

向 127.0.0.1 发送 Ping 请求
主机可达
向 173.194.32.38 发送 Ping 请求
主机可达

编辑:

您可以尝试修改代码以使用 getByAddress() 来获取地址:

public static void main(String[] args) throws UnknownHostException, IOException {
    InetAddress inet;

    inet = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
    System.out.println("Sending Ping Request to " + inet);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");

    inet = InetAddress.getByAddress(new byte[] { (byte) 173, (byte) 194, 32, 38 });
    System.out.println("Sending Ping Request to " + inet);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");
}

getByName() 方法可能会尝试某种在您的机器上可能无法进行的反向 DNS 查找,getByAddress() 可能会绕过它。

于 2012-07-16T14:51:32.607 回答
19

您不能简单地在 Java 中 ping,因为它依赖于 ICMP,遗憾的是 Java 不支持它

http://mindprod.com/jgloss/ping.html

改用套接字

希望能帮助到你

于 2012-07-16T15:48:29.553 回答
11

您可以使用此方法在 Windows 和其他平台上 ping 主机:

private static boolean ping(String host) throws IOException, InterruptedException {
    boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");

    ProcessBuilder processBuilder = new ProcessBuilder("ping", isWindows? "-n" : "-c", "1", host);
    Process proc = processBuilder.start();

    int returnVal = proc.waitFor();
    return returnVal == 0;
}
于 2013-08-03T07:05:06.740 回答
11

它肯定会起作用

import java.io.*;
import java.util.*;

public class JavaPingExampleProgram
{

  public static void main(String args[]) 
  throws IOException
  {
    // create the ping command as a list of strings
    JavaPingExampleProgram ping = new JavaPingExampleProgram();
    List<String> commands = new ArrayList<String>();
    commands.add("ping");
    commands.add("-c");
    commands.add("5");
    commands.add("74.125.236.73");
    ping.doCommand(commands);
  }

  public void doCommand(List<String> command) 
  throws IOException
  {
    String s = null;

    ProcessBuilder pb = new ProcessBuilder(command);
    Process process = pb.start();

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));

    // read the output from the command
    System.out.println("Here is the standard output of the command:\n");
    while ((s = stdInput.readLine()) != null)
    {
      System.out.println(s);
    }

    // read any errors from the attempted command
    System.out.println("Here is the standard error of the command (if any):\n");
    while ((s = stdError.readLine()) != null)
    {
      System.out.println(s);
    }
  }

}
于 2013-01-01T13:27:58.470 回答
7

简短的建议:不要使用 isReachable(),调用系统 ping,如上面一些答案中所建议的那样。

长解释:

  • ping 使用 ICMP 网络协议。要使用 ICMP,需要一个“原始套接字”
  • 操作系统不允许标准用户使用原始套接字
  • 以下适用于fedora 30 linux,windows系统应该类似
  • 如果 java 以 root 身份运行,isReachable() 实际上会发送 ICMP ping 请求
  • 如果 java 不以 root 身份运行,isReachable() 会尝试连接到 TCP 端口 7,即回显端口。该服务一般不再使用,尝试使用可能会产生不正确的结果
  • 对连接请求的任何类型的回答,也是一个拒绝(TCP 标志 RST)从 isReachable() 产生一个“真”
  • 一些防火墙会为任何未明确打开的端口发送 RST。如果发生这种情况,您将获得 isReachable() == true 对于甚至不存在的主机
  • 进一步尝试为 java 进程分配必要的功能:
  • setcap cap_net_raw+eip java 可执行文件(分配使用原始套接字的权利)
  • 测试:getcap java executable -> 'cap_net_raw+eip'(已分配能力)
  • 正在运行的 java 仍然向端口 7 发送 TCP 请求
  • 使用 getpcaps pid检查正在运行的 java 进程表明正在运行的 java 没有原始套接字功能。显然我的 setcap 已被某些安全机制覆盖
  • 随着安全要求的增加,这可能会变得更加受限,除非 sb 实现了一个特别是 ping 的异常(但到目前为止在网上没有发现任何东西)
于 2020-03-06T18:10:56.137 回答
3


只是对其他人给出的内容的补充,即使它们运行良好,但在某些情况下,如果互联网速度慢或存在一些未知的网络问题,某些代码将无法工作(isReachable())。但是下面提到的这段代码创建了一个进程,该进程充当 Windows 的命令行 ping (cmd ping)。它在所有情况下都适用于我,经过尝试和测试。

代码 :-

public class JavaPingApp {

public static void runSystemCommand(String command) {

    try {
        Process p = Runtime.getRuntime().exec(command);
        BufferedReader inputStream = new BufferedReader(
                new InputStreamReader(p.getInputStream()));

        String s = "";
        // reading output stream of the command
        while ((s = inputStream.readLine()) != null) {
            System.out.println(s);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {

    String ip = "stackoverflow.com"; //Any IP Address on your network / Web
    runSystemCommand("ping " + ip);
}
}

希望有帮助,加油!!!

于 2015-05-17T14:20:58.313 回答
3

尽管这不依赖于 Windows 上的 ICMP,但此实现与新的Duration API配合得很好

public static Duration ping(String host) {
    Instant startTime = Instant.now();
    try {
        InetAddress address = InetAddress.getByName(host);
        if (address.isReachable(1000)) {
            return Duration.between(startTime, Instant.now());
        }
    } catch (IOException e) {
        // Host not available, nothing to do here
    }
    return Duration.ofDays(1);
}
于 2018-08-29T09:02:50.283 回答
1

在带有 oracle-jdk 的 linux 上,OP 提交的代码在非 root 时使用端口 7,在 root 时使用 ICMP。当按照文档说明以 root 身份运行时,它会执行真正的 ICMP 回显请求。

如果您在 MS 机器上运行它,您可能必须以管理员身份运行应用程序才能获得 ICMP 行为。

于 2014-02-06T08:12:32.320 回答
1

我更喜欢这种方式:

   /**
     *
     * @param host
     * @return true means ping success,false means ping fail.
     * @throws IOException
     * @throws InterruptedException
     */
    private static boolean ping(String host) throws IOException, InterruptedException {
        boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");

        ProcessBuilder processBuilder = new ProcessBuilder("ping", isWindows? "-n" : "-c", "1", host);
        Process proc = processBuilder.start();
        return proc.waitFor(200, TimeUnit.MILLISECONDS);
    }

这种方式可以将阻塞时间限制在特定的时间,比如200毫秒。

在 MacOS、Android 和 Windows 上运行良好,应该在 JDK 1.8 中使用。

这个想法来自Mohammad Banisaeid,但我无法发表评论。(您必须有 50 声望才能发表评论)

于 2020-08-21T09:21:55.360 回答
1

这是一种 ping IP 地址的方法,该方法应该Java适用于系统:WindowsUnix

import org.apache.commons.lang3.SystemUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class CommandLine
{
    /**
     * @param ipAddress The internet protocol address to ping
     * @return True if the address is responsive, false otherwise
     */
    public static boolean isReachable(String ipAddress) throws IOException
    {
        List<String> command = buildCommand(ipAddress);
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        Process process = processBuilder.start();

        try (BufferedReader standardOutput = new BufferedReader(new InputStreamReader(process.getInputStream())))
        {
            String outputLine;

            while ((outputLine = standardOutput.readLine()) != null)
            {
                // Picks up Windows and Unix unreachable hosts
                if (outputLine.toLowerCase().contains("destination host unreachable"))
                {
                    return false;
                }
            }
        }

        return true;
    }

    private static List<String> buildCommand(String ipAddress)
    {
        List<String> command = new ArrayList<>();
        command.add("ping");

        if (SystemUtils.IS_OS_WINDOWS)
        {
            command.add("-n");
        } else if (SystemUtils.IS_OS_UNIX)
        {
            command.add("-c");
        } else
        {
            throw new UnsupportedOperationException("Unsupported operating system");
        }

        command.add("1");
        command.add(ipAddress);

        return command;
    }
}

确保添加Apache Commons Lang到您的依赖项。

于 2015-09-17T18:28:39.550 回答
0

我知道以前的条目已经回答了这个问题,但是对于遇到这个问题的其他人,我确实找到了一种不需要在 Windows 中使用“ping”过程然后擦洗输出的方法。

我所做的是使用 JNA 调用 Window 的 IP 帮助程序库来执行 ICMP 回显

查看我自己对我自己的类似问题的回答

于 2014-09-18T17:34:11.703 回答
0

InetAddress 并不总是返回正确的值。在本地主机的情况下成功,但对于其他主机,这表明主机无法访问。尝试使用 ping 命令,如下所示。

try {
    String cmd = "cmd /C ping -n 1 " + ip + " | find \"TTL\"";        
    Process myProcess = Runtime.getRuntime().exec(cmd);
    myProcess.waitFor();

    if(myProcess.exitValue() == 0) {

    return true;
    }
    else {
        return false;
    }
}
catch (Exception e) {
    e.printStackTrace();
    return false;
}
于 2018-03-02T09:56:13.683 回答
0

我尝试了几个选项:

  1. Java 网络地址

InetAddress.getByName(ipAddress),尝试几次后,Windows 上的网络开始出现异常

  1. Java HttpURL 连接

            URL siteURL = new URL(url);
            connection = (HttpURLConnection) siteURL.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(pingTime);
            connection.connect();
    
            code = connection.getResponseCode();
            if (code == 200) {
                code = 200;
            }.
    

这是可靠的,但有点慢

  1. Windows 批处理文件

我终于决定在我的 Windows 机器上创建一个包含以下内容的批处理文件:ping.exe -n %echoCount% %pingIp% 然后我在我的 java 代码中调用了 .bat 文件,使用

public int pingBat(Network network) {
ProcessBuilder pb = new ProcessBuilder(pingBatLocation);
Map<String, String> env = pb.environment();

env.put(
        "echoCount", noOfPings + "");
env.put(
        "pingIp", pingIp);
File outputFile = new File(outputFileLocation);
File errorFile = new File(errorFileLocation);

pb.redirectOutput(outputFile);

pb.redirectError(errorFile);

Process process;

try {
    process = pb.start();
    process.waitFor();
    String finalOutput = printFile(outputFile);
    if (finalOutput != null && finalOutput.toLowerCase().contains("reply from")) {
        return 200;
    } else {
        return 202;
    }
} catch (IOException e) {
    log.debug(e.getMessage());
    return 203;
} catch (InterruptedException e) {
    log.debug(e.getMessage());
    return 204;
}

}

事实证明这是最快最可靠的方法

于 2019-03-27T07:07:48.533 回答
-3

这应该有效:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Pinger {

private static String keyWordTolookFor = "average";

public Pinger() {
    // TODO Auto-generated constructor stub
}


 public static void main(String[] args) {
 //Test the ping method on Windows.
 System.out.println(ping("192.168.0.1")); }


public String ping(String IP) {
    try {
        String line;
        Process p = Runtime.getRuntime().exec("ping -n 1 " + IP);
        BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while (((line = input.readLine()) != null)) {

            if (line.toLowerCase().indexOf(keyWordTolookFor.toLowerCase()) != -1) {

                String delims = "[ ]+";
                String[] tokens = line.split(delims);
                return tokens[tokens.length - 1];
            } 
        }

        input.close();
    } catch (Exception err) {
        err.printStackTrace();
    }
    return "Offline";
}

}

于 2017-03-02T01:22:23.490 回答