全部
This commit is contained in:
120
src/main/java/com/yj/earth/common/util/NetUtils.java
Normal file
120
src/main/java/com/yj/earth/common/util/NetUtils.java
Normal file
@ -0,0 +1,120 @@
|
||||
package com.yj.earth.common.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* 网络工具类
|
||||
*/
|
||||
public class NetUtils {
|
||||
private static final Logger logger = LoggerFactory.getLogger(NetUtils.class);
|
||||
|
||||
// Ping 超时时间(毫秒)
|
||||
private static final int PING_TIMEOUT = 500;
|
||||
// TCP Ping 端口
|
||||
private static final int TCP_PING_PORT = 80;
|
||||
// TCP Ping 超时时间(毫秒)
|
||||
private static final int TCP_TIMEOUT = 1500;
|
||||
|
||||
private static final ExecutorService PING_EXECUTOR = Executors.newFixedThreadPool(
|
||||
Math.min(Runtime.getRuntime().availableProcessors() * 2, 50),
|
||||
new ThreadFactory() {
|
||||
private int count = 0;
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setName("ping-executor-" + (count++));
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 使用 ICMP Echo Request (标准 Ping) 检测主机是否可达
|
||||
* @param ipAddress IP地址或主机名
|
||||
* @return true if reachable, false otherwise
|
||||
*/
|
||||
public static boolean isReachableByIcmp(String ipAddress) {
|
||||
if (ipAddress == null || ipAddress.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(ipAddress);
|
||||
// isReachable 会尝试 ICMP Echo 和 TCP Echo (端口 7)
|
||||
return address.isReachable(PING_TIMEOUT);
|
||||
} catch (UnknownHostException e) {
|
||||
logger.warn("未知的主机: {}", ipAddress);
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
// 发生 IO 异常、视为不可达
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 TCP 连接检测主机端口是否开放(模拟 Ping)
|
||||
* 当 ICMP 被防火墙禁止时、此方法更有效
|
||||
* @param ipAddress IP地址
|
||||
* @param port 端口号
|
||||
* @return true if port is open, false otherwise
|
||||
*/
|
||||
public static boolean isReachableByTcp(String ipAddress, int port) {
|
||||
if (ipAddress == null || ipAddress.trim().isEmpty() || port < 1 || port > 65535) {
|
||||
return false;
|
||||
}
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = new Socket();
|
||||
socket.connect(new java.net.InetSocketAddress(ipAddress, port), TCP_TIMEOUT);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
// 连接失败、端口未开放或主机不可达
|
||||
return false;
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步并发检测多个IP的可达性
|
||||
* @param ips 需要检测的IP列表
|
||||
* @return 一个 Map、key 是 IP、value 是 Boolean (是否在线)
|
||||
* @throws ExecutionException 执行异常
|
||||
* @throws InterruptedException 线程中断异常
|
||||
*/
|
||||
public static Map<String, Boolean> checkReachabilityAsync(Collection<String> ips) throws ExecutionException, InterruptedException {
|
||||
if (ips == null || ips.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
List<Callable<Map.Entry<String, Boolean>>> tasks = new ArrayList<>();
|
||||
for (String ip : ips) {
|
||||
tasks.add(() -> {
|
||||
boolean isOnline = isReachableByTcp(ip, TCP_PING_PORT) || isReachableByIcmp(ip);
|
||||
return new AbstractMap.SimpleEntry<>(ip, isOnline);
|
||||
});
|
||||
}
|
||||
|
||||
List<Future<Map.Entry<String, Boolean>>> futures = PING_EXECUTOR.invokeAll(tasks);
|
||||
Map<String, Boolean> results = new ConcurrentHashMap<>();
|
||||
for (Future<Map.Entry<String, Boolean>> future : futures) {
|
||||
Map.Entry<String, Boolean> entry = future.get();
|
||||
results.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user