@liruiyi962464
2025-07-22T07:15:24.000000Z
字数 8737
阅读 136
代码
public void monitorUseState() {
List<ZcMonitor> zcMonitorList = zcMonitorService.list();
Integer flag = 0;
if(zcMonitorList.size() > 0 && zcMonitorList != null) {
for (int i = 0; i < zcMonitorList.size(); i++) {
String ip = zcMonitorList.get(i).getIp();
String name = zcMonitorList.get(i).getName();
String position = zcMonitorList.get(i).getPosition();
// 当返回值是true时,说明监控IP是可用的,false则不可。
int timeOut = 3000; // 超时应该在3钞以上
boolean status = false;
try {
// status = InetAddress.getByName(ip).isReachable(timeOut);
InetAddress address = InetAddress.getByName(ip);
System.out.println("开始检查 IP 地址 " + ip + " 是否可达...");
long startTime = System.currentTimeMillis();
status = address.isReachable(timeOut);
long endTime = System.currentTimeMillis();
System.out.println("检查完成,耗时:" + (endTime - startTime) + " 毫秒");
if (status) {
System.out .println("IP 地址 " + ip + " 是可达的");
} else {
System.out.println("IP 地址 " + ip + " 不可达");
}
} catch (IOException e) {
e.printStackTrace();
}
//System.err.println("监控ip"+ip+"状态"+status);
//onlineOrNot lineOrNot = new onlineOrNot();
//String userAndPwd = onlineOrNot.userAndPwd(ip, username, password);
if (!status) {
// 状态更新到数据库
zcMonitorList.get(i).setUseState("1");
zcMonitorService.updateById(zcMonitorList.get(i));
// 离线(在线状态不用推送)
System.err.println("监控IP:【"+ip+"】监控名称:【"+name+"】监控位置:【"+position+"】【已离线】");
zcWarningInformationService.warnXiaoxi(3,"监控IP:【"+ip+"】监控名称:【"+name+"】监控位置:【"+position+"】【已离线】",zcMonitorList.get(i));
}else {
// 状态更新到数据库
zcMonitorList.get(i).setUseState("2");
zcMonitorService.updateById(zcMonitorList.get(i));
}
}
}
}
public Result<?> pingDevice(@RequestParam(name="ip") String ip) throws Exception {
List<String> pingContent = new ArrayList<>();
boolean b = Ping.ping(ip);
if (b){
pingContent = Ping.pingA(ip);
} else {
String message = "目标主机"+ip+"无法访问,请检查!";
pingContent.add(message);
}
return Result.OK(pingContent);
}
package org.jeecg.modules.quartz.job;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.demo.alarmManagement.entity.AlarmRecord;
import org.jeecg.modules.demo.alarmManagement.service.IAlarmRecordService;
import org.jeecg.modules.demo.ping.Ping;
import org.jeecg.modules.demo.system.entity.DeviceInfo;
import org.jeecg.modules.demo.system.service.IDeviceInfoService;
import org.jeecg.modules.message.websocket.WebSocket;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* 多线程定时任务(带线程池)
* @Author Scott
*/
@Slf4j
public class PingLuYouJob implements Job {
@Autowired
private IDeviceInfoService deviceInfoService;
@Autowired
private IAlarmRecordService alarmRecordService;
@Autowired
private WebSocket webSocket;
@Autowired
private RedisUtil redisUtil;
// 定义线程池参数
private static final int CORE_POOL_SIZE = 5; // 核心线程数
private static final int MAX_POOL_SIZE = 10; // 最大线程数
private static final int QUEUE_CAPACITY = 100; // 队列容量
@SneakyThrows
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 获取设备信息列表
List<DeviceInfo> deviceInfoList = deviceInfoService.list();
// 创建线程池
ExecutorService executor = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(QUEUE_CAPACITY)
);
// 用于收集检测结果
ConcurrentHashMap<String, Boolean> pingResults = new ConcurrentHashMap<>();
try {
// 提交所有ping任务到线程池
int maxAttempts = 5; // 最大尝试5次
int successThreshold = 3; // 成功3次即认为可用
int timeoutPerAttempt = 3000; // 每次ping超时3秒
for (DeviceInfo deviceInfo : deviceInfoList) {
String targetIp = deviceInfo.getIp();
executor.submit(() -> {
boolean result = false;
try {
// result = Ping.ping(ip);
result = Ping.pingWithRetry(targetIp, maxAttempts, successThreshold, timeoutPerAttempt);
} catch (Exception e) {
result = false;
}
pingResults.put(targetIp, result);
});
}
// 关闭线程池并等待任务完成
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
log.warn("线程池未在指定时间内完成所有任务");
}
// 处理检测结果
for (DeviceInfo deviceInfo : deviceInfoList) {
String ip = deviceInfo.getIp();
boolean pingResult = pingResults.getOrDefault(ip, false);
if (pingResult) {
deviceInfo.setState("1");
} else {
if ("1".equals(deviceInfo.getState())) {
// 添加报警记录
AlarmRecord alarmRecord = new AlarmRecord();
alarmRecord.setDeviceId(deviceInfo.getId());
alarmRecord.setAlarmContent(deviceInfo.getName() + "设备未ping通,设备处于离线状态;");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
alarmRecord.setAlarmTime(sdf.format(new Date()));
alarmRecord.setAlarmType("1");
alarmRecordService.save(alarmRecord);
// 推送告警信息
String[] usersRecord = alarmRecordService.getSetUsersRecord();
webSocket.sendMessage(usersRecord, "-" + deviceInfo.getName() + "设备未ping通,设备处于离线状态;" + "$" + sdf.format(new Date()));
// 删除redis缓存
redisUtil.del(deviceInfo.getId());
}
deviceInfo.setState("0");
deviceInfo.setSimState("0");
deviceInfo.setModuleState("0");
}
deviceInfoService.updateById(deviceInfo);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("线程池被中断", e);
} finally {
executor.shutdownNow(); // 确保线程池关闭
}
}
}
package org.jeecg.modules.demo.ping;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Ping {
public static boolean ping(String ipAddress) throws Exception {
int timeOut = 3000 ; // 超时应该在3钞以上
boolean status = InetAddress.getByName(ipAddress).isReachable(timeOut); // 当返回值是true时,说明host是可用的,false则不可。
return status;
}
/**
* 带重试机制的Ping检测方法
* @param ipAddress 目标主机IP地址(如:"8.8.8.8")
* @param maxAttempts 最大尝试次数(建议3-5次,根据网络稳定性调整)
* @param successThreshold 成功判定阈值(建议设置为maxAttempts的60%-80%)
* @param timeoutPerAttempt 单次尝试超时时间(单位:毫秒,建议3000-5000ms)
* @return 达到成功阈值返回true,否则返回false
*/
public static boolean pingWithRetry(String ipAddress, int maxAttempts, int successThreshold, int timeoutPerAttempt) {
int successCount = 0;
for (int i = 0; i < maxAttempts; i++) {
try {
boolean isReachable = InetAddress.getByName(ipAddress).isReachable(timeoutPerAttempt);
if (isReachable) {
successCount++;
System.out.println("Attempt " + (i + 1) + ": Success");
// 提前退出条件:成功次数达到阈值
if (successCount >= successThreshold) {
return true;
}
} else {
System.out.println("Attempt " + (i + 1) + ": Failed");
}
// 可选:添加短暂间隔避免频繁请求(例如1秒)
Thread.sleep(1000);
} catch (UnknownHostException e) {
System.err.println("Invalid host: " + e.getMessage());
return false;
} catch (IOException e) {
System.err.println("IO Error: " + e.getMessage());
return false;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("Thread interrupted");
return false;
}
}
System.out.println("Final success count: " + successCount + "/" + maxAttempts);
return successCount >= successThreshold;
}
public static void main(String[] args) {
String targetIp = "8.8.8.8"; // 示例IP
int maxAttempts = 5; // 最大尝试5次
int successThreshold = 3; // 成功3次即认为可用
int timeoutPerAttempt = 3000; // 每次ping超时3秒
boolean finalStatus = pingWithRetry(targetIp, maxAttempts, successThreshold, timeoutPerAttempt);
System.out.println("Host is reachable: " + finalStatus);
}
public static List<String> ping02(String ipAddress) throws Exception {
List<String> outputLines = new ArrayList<>(); // 用于保存输出的集合
try {
Process pro = Runtime.getRuntime().exec("ping " + ipAddress);
BufferedReader buf = new BufferedReader( new InputStreamReader(
pro.getInputStream(),"GBK"));
int i =1;
String line = null;
while ((line = buf.readLine()) != null)
System.out.println(line);
outputLines.add(line);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
return outputLines;
}
public static boolean ping(String ipAddress, int pingTimes, int timeOut) {
BufferedReader in = null;
Runtime r = Runtime.getRuntime(); // 将要执行的ping命令,此命令是windows格式的命令
String pingCommand = "ping " + ipAddress + " -n " + pingTimes + " -w " + timeOut;
try { // 执行命令并获取输出
System.out.println(pingCommand);
Process p = r.exec(pingCommand);
if (p == null) {
return false;
}
in = new BufferedReader( new InputStreamReader(p.getInputStream())); // 逐行检查输出,计算类似出现=23ms TTL=62字样的次数
int connectedCount = 0;
String line = null;
while ((line = in.readLine()) != null) {
connectedCount += getCheckResult(line);
} // 如果出现类似=23ms TTL=62这样的字样,出现的次数=测试次数则返回真
return connectedCount == pingTimes;
} catch (Exception ex) {
ex.printStackTrace(); // 出现异常则返回假
return false;
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 若line含有=18ms TTL=16字样,说明已经ping通,返回1,否則返回0.
private static int getCheckResult(String line) { // System.out.println("控制台输出的结果为:"+line);
Pattern pattern = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
return 1;
}
return 0;
}
public static List<String> pingA(String ipAddress){
List<String> outputLines = new ArrayList<>(); // 用于保存输出的集合
try {
// 创建一个Process实例执行ping命令
Process process = Runtime.getRuntime().exec("ping " + ipAddress);
// 读取ping命令的输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK"));
String line;
while ((line = reader.readLine()) != null) {
outputLines.add(line); // 将每行输出添加到集合中
}
// 等待ping命令执行完成
int exitCode = process.waitFor();
System.out.println("Ping命令执行完成,退出码: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
return outputLines;
}
}