以下代码针对/24 IP 主机列表执行 254 个 ping 请求,每个请求都在其自己的线程中(或者这就是我的想法)。完整的/24 子网 (172.21.0.0/24) 被加载到 hostList 中,然后在 for 循环中传递给工作线程以启动每个线程以完成 ping 工作。
每个 ping 线程的超时时间为 1000 毫秒,因此,如果将 254 个 IP 传递给 254 个线程,则整个过程不应超过一到两秒。
即如果程序确实是多线程的,我应该能够在 2 秒内 ping 通此/24 中的所有 ip。
结果似乎是串联而不是并行地对每个主机执行 ping 操作...在使其成为真正的多线程 ping 应用程序方面我做错了什么?
/*
* Step 1: Ping a subnet to find alive hosts
*/
package smartsdiscoveryrobot;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.icmp4j.IcmpPingUtil;
import org.icmp4j.IcmpPingRequest;
import org.icmp4j.IcmpPingResponse;
import org.apache.commons.net.util.SubnetUtils; // Subnet Utils to genrate host list
/**
*
* @author beukesmar
*/
public class PingExecutorService {
private static final String COMMUNITY = "public";
private static final int NUMBEROFPINGS = 1;
private static final int PINGTIMEOUT = 1000;
//Determine how many threads should be spawned by fetching the number of processors from Runtime
//private static final int NUM_THREADS = Runtime.getRuntime().availableProcessors();
private static final int NUM_THREADS = 254; //Runtime.getRuntime().availableProcessors();
public static void main(String args[]) throws Exception {
System.out.println("Availabe threads: " + NUM_THREADS);
// Instantitate new Fixed size thread pool with NUM_THREADS
ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
SubnetUtils utils = new SubnetUtils("172.21.0.1", "255.255.255.0");
System.out.println("Low Address: " + utils.getInfo().getLowAddress());
System.out.println("High Address: " + utils.getInfo().getHighAddress());
// Construct hostList with all IP's in above subnet
String[] hostList = utils.getInfo().getAllAddresses();
// Create worker for each host in hostlist
System.out.println("Host array length: " + hostList.length);
for (String host : hostList) {
Runnable worker = new MyRunnable(host, PINGTIMEOUT, COMMUNITY);
executor.execute(worker);
}
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated()) {
}
System.out.println("\nFinished all threads");
}
public static class MyRunnable implements Runnable {
private final String host;
private final String community;
private final int pingtimeout;
MyRunnable(String host, int pingtimeout, String community) {
this.host = host;
this.pingtimeout = pingtimeout;
this.community = community;
}
@Override
public void run() {
System.out.print("Spawning new thread to ping to host: " + host + " timeout=" + pingtimeout + "\n");
/*
Code to perform ping
*/
final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest();
request.setHost(host);
request.setTimeout(pingtimeout);
request.setPacketSize(32); // Send 32 bytes
// Perform NUMBEROFPINGS pings per host
int numberofpings = NUMBEROFPINGS;
int numberofsuccesspings = 0;
int numberoffailedresponse = 0;
int minlatency = 0;
long avglatency = 0;
int maxlatency = 0;
int sumoflatency = 0;
long totaltime = 0;
boolean isalive = false;
boolean haspacketloss = false;
for (int i = 1; i <= numberofpings; i++) {
final IcmpPingResponse response = IcmpPingUtil.executePingRequest(request);
// host responded to a echo request
if (response.getSuccessFlag() == true) {
isalive = true;
numberofsuccesspings++;
//System.out.println("Reply from " + host + " icmp_req=" + i + " bytes=" + response.getSize() + " time=" + response.getRtt() + "ms");
// Set inital values
if (minlatency == 0) {
minlatency = response.getRtt();
maxlatency = response.getRtt();
}
// Set minlatency if response latency is lower than minlatency
if (response.getRtt() < minlatency) {
minlatency = response.getRtt();
}
// Set maxlatency if response latency is higher than maxlatency
if (response.getRtt() > maxlatency) {
maxlatency = response.getRtt();
}
sumoflatency = sumoflatency + response.getRtt();
totaltime = totaltime + response.getDuration();
// host has dropped a echo request packet
} else {
haspacketloss = true;
numberoffailedresponse++;
//System.out.println("Reply from " + host + ":Error:" + response.getErrorMessage());
totaltime = totaltime + response.getDuration();
}
//final String formattedResponse = IcmpPingUtil.formatResponse(response);
//System.out.println(host + ":" + formattedResponse);
}
long packetloss = numberoffailedresponse / numberofpings * 100;
// Dont devide by 0
if (numberofsuccesspings != 0) {
avglatency = sumoflatency / numberofsuccesspings;
}
/*System.out.println(
"---" + host + " ping statistics ---\n"
+ numberofpings + " packets transmitted, " + numberofsuccesspings + ", " + packetloss + "% packet loss, time " + totaltime + "ms\n"
+ "rtt min/avg/max = " + minlatency + "/" + avglatency + "/" + maxlatency + " ms");*/
System.out.println(host + " isalive=" + isalive + " haspacketloss=" + haspacketloss);
}
}
}
最佳答案
icmp4j 似乎无法并行 ping,它一次执行 1 个 ping。
我不确定为什么,大胆猜测:可能与 jna 有关。
我的解决方案是使用processbuilder来执行 native ping命令。
关于Java icmp4j 多线程 ping 不那么多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38935271/