利用 InetAddress.isReachable(timeout) 發送 ICMP 回顯請求(需 Root 權限)或 TCP 回聲協議(非 Root)探測主機可達性,統計延遲與丟包率。
SimplePing 設計亮點wait() 直到所有探測完成或超時。public class SimplePing implements Runnable {
private final Object lock = new Object();
private int count, timeout, arrived;
private float lossRate, avgDelay;
private String host, resolvedIp;
public SimplePing(String host, int count, int timeout) {
this.host = host; this.count = count; this.timeout = timeout;
for (int i = 0; i < count; i++) new Thread(this).start();
synchronized(lock) { try { lock.wait(); } catch (InterruptedException ignored) {} }
}
@Override public void run() {
long start = System.currentTimeMillis();
boolean reachable = false;
try {
InetAddress addr = InetAddress.getByName(host);
reachable = addr.isReachable(timeout);
if (reachable) resolvedIp = addr.getHostAddress();
} catch (IOException ignored) {}
long delay = System.currentTimeMillis() - start;
recordResult(reachable, delay);
}
private void recordResult(boolean ok, long delay) {
synchronized(lock) {
if (ok) { arrived++; avgDelay = (avgDelay + delay) / 2f; }
if (--count == 0) { lossRate = 1f - arrived/(float)(count+arrived); lock.notifyAll(); }
}
}
// getter 方法...
}
SimplePing ping = new SimplePing("www.baidu.com", 4, 3000);
System.out.println("IP: " + ping.getIp());
System.out.println("丟包率: " + ping.getLossRate());
System.out.println("平均延遲: " + ping.getDelay() + "ms");
System.out.println("是否可達: " + ping.getIsSucceed());
isReachable 非 Root 環境下退化為 TCP 連接嘗試(默認端口 7),非真正 ICMP Ping,可能誤判。ping 命令解析輸出,或使用 JNI 調用底層 ICMP。