实现一个用于执行 Ping 命令并监测主机可达性的线程类。它的作用是通过执行 Ping 命令来检查指定 IP 地址的主机是否可达,并获取相关的响应时间和丢包率信息。
代码中的 PingThread
类同样继承自 Thread
,意味着它可以在单独的线程中执行。
在 run
方法中,根据操作系统类型(Windows 或 Linux),构建相应的 Ping 命令,并使用 Runtime.getRuntime().exec()
方法执行该命令。通过读取命令输出的结果,解析出丢包率和响应时间的信息。
在 Windows 系统下,命令输出的行中包含 "时间=" 的字符串,从中解析出响应时间。而在 Linux 系统下,命令输出的行中同样包含 "时间=" 的字符串,但后面跟着的是以毫秒为单位的时间。根据操作系统的不同,可以使用不同的解析方式来提取响应时间。
此外,命令输出中还包含有关已发送和已接收数据包数量的信息,通过正则表达式匹配来解析出这些信息,并计算出丢包率。
根据解析出的数据,更新监控主机的状态、平均响应时间和丢包率,通过调用 monPingService
完成状态的更新。
该线程在每次 Ping 命令执行完成后会等待一段时间(这里是 5000 毫秒),然后再次执行 Ping 命令。通过 running
变量控制线程的运行状态,当调用 stopThread
方法时,将设置 running
为 false
,从而终止线程的执行。
请注意,该代码片段中使用了一些自定义的类和接口,例如 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);
}
}
}
}