2016-08-13 61 views
1

下面的代码针对/ 24 IP hostList执行254个ping请求,每个请求都在它自己的线程中(或者我认为是这样)。一个完整的/ 24子网(172.21.0.0/24)被加载到hostList中,然后通过for循环传递给worker,以踢每个线程来完成ping工作。Java icmp4j多线程ping不是如此多线程

每个ping线程的超时时间是1000ms,所以如果254个IP被传递给254个线程,整个过程不应该花费超过一秒到两秒。

即如果程序确实是多线程的话,我应该可以在2秒内将所有的ip都ping到这个/ 24中。

结果似乎是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); 
     } 
    } 
} 
+0

您的计算机上有固定数量的内核。这个数字可能在1到16之间(取决于你如何计算“内核”);最有可能4或8(再次,取决于)。这是您可以在CPU上运行的真正并发事物的最大数量。如果你想要交叉这些,你必须进入异步I/O。 –

+0

@ T.J.Crowder,一个在系统调用中被阻塞的线程,等待对ping的回复不计入内核数量。线程比多核CPU要长很多。人们开始使用它们的主要原因之一是因为使用不同的线程在不同的文件/设备/网络端口上进行同步I/O调用比进行异步I/O调用更容易理解。 –

+0

@jameslarge:如果是系统调用,是的。但是,异步I/O往往比多线程同步I/O更好。 –

回答

0

icmp4j似乎无法并行ping,它一次执行1次ping操作。

我不知道为什么,狂猜:可能与jna有关。

我的解决方案是使用processbuilder来执行本机ping命令。