@liruiyi962464
2025-07-22T07:15:24.000000Z
字数 8737
阅读 146
代码
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*/@Slf4jpublic class PingLuYouJob implements Job {@Autowiredprivate IDeviceInfoService deviceInfoService;@Autowiredprivate IAlarmRecordService alarmRecordService;@Autowiredprivate WebSocket webSocket;@Autowiredprivate 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@Overridepublic 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"; // 示例IPint 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;}}