Java icmp4j 多线程 ping 不那么多线程

标签 java multithreading

以下代码针对/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/

相关文章:

c++ 将各种参数传递给父类构造函数(线程c++11)

java - 为什么我的 ArrayBlockingQueue 在放入列表后会导致空队列?

java - Maven Jetty 插件中的 Jetty JNDI 错误

java - 线程 "main"java.util.InputMismatchException 使用 Double 时出现异常

Java检查用户是否在控制台中输入

c# - .NET 2.0 的类 TPL 库

java - 从列表中的任何值获取键

java - 如何捕获来自未知 USB OTG 设备的信号?

python - 在大文件上使用 Pandas 数据透视表的最有效方法

c++ - 是否可以全局声明一个boost线程?