Java网络编程-Ping监测

实现一个用于执行 Ping 命令并监测主机可达性的线程类。它的作用是通过执行 Ping 命令来检查指定 IP 地址的主机是否可达,并获取相关的响应时间和丢包率信息。

代码中的 PingThread 类同样继承自 Thread,意味着它可以在单独的线程中执行。

run 方法中,根据操作系统类型(Windows 或 Linux),构建相应的 Ping 命令,并使用 Runtime.getRuntime().exec() 方法执行该命令。通过读取命令输出的结果,解析出丢包率和响应时间的信息。

在 Windows 系统下,命令输出的行中包含 "时间=" 的字符串,从中解析出响应时间。而在 Linux 系统下,命令输出的行中同样包含 "时间=" 的字符串,但后面跟着的是以毫秒为单位的时间。根据操作系统的不同,可以使用不同的解析方式来提取响应时间。

此外,命令输出中还包含有关已发送和已接收数据包数量的信息,通过正则表达式匹配来解析出这些信息,并计算出丢包率。

根据解析出的数据,更新监控主机的状态、平均响应时间和丢包率,通过调用 monPingService 完成状态的更新。

该线程在每次 Ping 命令执行完成后会等待一段时间(这里是 5000 毫秒),然后再次执行 Ping 命令。通过 running 变量控制线程的运行状态,当调用 stopThread 方法时,将设置 runningfalse,从而终止线程的执行。

请注意,该代码片段中使用了一些自定义的类和接口,例如 IMonPingService,这些类和接口在代码中没有给出具体实现。因此,要使代码正常运行,需要确保相关的类和接口已经正确实现,并且适配于你的应用程序环境

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PingThread extends Thread{


    private volatile boolean running = true;
    private Long pingId;
    private String ipAddress;
    private Long pingCount;
    private Long timeout;
    private IMonPingService monPingService;


    public PingThread(Long pingId, String ipAddress,Long pingCount,Long timeout, IMonPingService monPingService){
        this.pingId = pingId;
        this.ipAddress = ipAddress;
        this.pingCount = pingCount == null ? 5:pingCount;
        this.timeout = timeout == null ? 1000:timeout;
        this.monPingService = monPingService;
    }

    public void stopThread() {
        running = false;
    }

    public void run() {
        String os = System.getProperty("os.name").toLowerCase();
        String pingCommand = os.contains("win") ? "ping -n "+pingCount+" -w "+timeout+" " + ipAddress : "ping -c "+pingCount+" -W "+timeout+" " + ipAddress;
        System.out.println("正在 ping:"+pingCommand);
        while (running){
            try {
                // 执行ping命令
                Process process = Runtime.getRuntime().exec(pingCommand);
                BufferedReader reader = os.contains("win") ?
                        new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"))
                        :new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"))
                        ;


                String line;
                int packetSent = 0;
                int packetReceived = 0;
                double totalResponseTime = 0;

                // 读取ping命令输出
                while ((line = reader.readLine()) != null) {
//                    System.out.println(line);
                    // 解析ping命令输出,获取丢包率和响应时间
                    // 来自 192.168.1.9 的回复: 字节=32 时间=1ms TTL=64
                    if (os.contains("win") && line.contains("时间=")) {
                        packetSent++;
                        packetReceived++;
                        int startIndex = line.indexOf("时间=") + 3;
                        int endIndex = line.indexOf("ms");
                        double responseTime = Double.parseDouble(line.substring(startIndex, endIndex).trim());
                        totalResponseTime += responseTime;
                    }
                    //64 字节,来自 192.168.1.9: icmp_seq=1 ttl=64 时间=0.786 毫秒
                    else if (os.contains("linux") && line.contains("时间=")) {
                        packetSent++;
                        packetReceived++;
                        int startIndex = line.indexOf("时间=") + 3;
                        int endIndex = line.indexOf(" 毫秒");
                        double responseTime = Double.parseDouble(line.substring(startIndex, endIndex).trim());
                        totalResponseTime += responseTime;
                    } else if (line.contains("已发送") && line.contains("已接收")) {
                        Pattern packetPattern = Pattern.compile("(\\d+) 个包");
                        Matcher packetMatcher = packetPattern.matcher(line);
                        if (packetMatcher.find()) {
                            packetSent = Integer.parseInt(packetMatcher.group(1));
                        }

                        Pattern lossPattern = Pattern.compile("(\\d+)% 包丢失");
                        Matcher lossMatcher = lossPattern.matcher(line);
                        if (lossMatcher.find()) {
                            int packetLossPercentage = Integer.parseInt(lossMatcher.group(1));
                            packetReceived = packetSent - (packetSent * packetLossPercentage) / 100;
                        }
                    }
                }

                if (packetSent > 0) {
                    double packetLossRate = (packetSent - packetReceived) / (double) packetSent * 100;
                    double averageResponseTime = totalResponseTime / (double) packetReceived;

//                    System.out.println("IP地址可达性:可达");
//                    System.out.println("平均响应时间:" + averageResponseTime + "ms");
//                    System.out.println("丢包率:" + packetLossRate + "%");
                    monPingService.updateMonPingStatus(pingId, Status.OPEN, BigDecimal.valueOf(averageResponseTime),BigDecimal.valueOf(packetLossRate));
                } else {
//                    System.out.println("IP地址不可达");
                    monPingService.updateMonPingStatus(pingId, Status.CLOSE,BigDecimal.valueOf(-1),BigDecimal.valueOf(100));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }


}

你可能感兴趣的:(JAVA随记,java,网络,ping)