2015-08-28 74 views
2

我正在用Java写一个简单的网络生存工具。它基本上只需要ping变量地址范围并将答案保存在数据库中。Java:线程不会同时ping通

起初,我用java.net库,但由于它只是使用echo命令,打印机,路由器和某些服务器在网络中不会回答。所以我使用了icmp4j库。

既然花了大约10到15分钟逐一做,当它来ping的254,一个地址范围,我决定使用线程扫描时间保持在最低限度。然而问题在于,它一次只能打一个地址。

我从来没有使用线程工作过,所以这里是代码,以防万一我犯了一个巨大的错误:

//the AddressRange class just saves the current address and counts it up by one 
    AddressRange ar = new AddressRange(tFStart.getText(), tFEnd.getText(), false); 

    //next() checks, if the last address is reached and returns false, if that is the case 
    while(ar.next()){ 
     try{ 
      //here, I create and start the threads 
      new Thread(new Ping(ar.getAddress())).start(); 
     } catch (Exception f) {} 

     //counts up the address by one 
     ar.countUp(ar.getAddressBits()); 
    } 

这里是我的平安等级:

public class Ping implements Runnable{ 

private final String address; 

public Ping(String address){ 
    this.address = address; 
} 
@Override 
public void run() { 

     IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest(); 
     request.setHost(address); 

    try{    
     IcmpPingResponse response = IcmpPingUtil.executePingRequest(request); 
     String formattedResponse = IcmpPingUtil.formatResponse(response); 
     String output = "Destination: " + address + " \n" + formattedResponse + " \n"; 

     if(formattedResponse.contains("Reply")){ 
      InetAddress addr = InetAddress.getByName(address); 
      output += "Hostname: " + verifyHostName(addr.getHostName()) + " \n"; 
      System.out.println(output); 
      saveClient(new PingData(output)); 
     } 

    } catch (Exception f) {} 
} 
} 

当我用java.net库替换了icmp4j-,线程同时被处理。我读过,线程不应该访问相同的资源,所以我想,这就是发生在这里的事情。但我还没有经验来分析甚至重写库。

这里是没有icmp4j的使用我的平安等级:

public class Ping implements Runnable{ 

private final String address; 

public Ping(String address){ 
    this.address = address; 
} 
@Override 
public void run() { 

    try{ 
     InetAddress addr = InetAddress.getByName(address); 

     if(addr.isReachable()){ 
      String output += "Hostname: " + verifyHostName(addr.getHostName()) + " \n"; 
      System.out.println(output); 
      saveClient(new PingData(output)); 
     } 
    } catch (Exception f) {} 
} 
} 

所以我想问,如果我犯了一个错误,或者如果有人有与所述库的经验,知道如何解决这个问题,或者有一个很好的选择,它完成了工作。

+0

无关:'StringBuilder'就是这样一个* core *类,它甚至在'java.lang'包中。编写自己的类并调用它'StringBuilder'将会让任何读取你的代码的人都感到困惑。 – Andreas

+0

谢谢,我不知道。我会纠正它。 :) – Sebowski

+0

我刚刚写了程序来ping多线程的IP 140和它对icmp4j库的工作正常,但正如你所说,Java的网络库是给予意想不到的结果。在不到一秒钟的时间里,我得到了100次ping结果。你是否收到任何错误或异常?通过逐个删除ping步骤彻底调试它! –

回答

1
  1. 要回答你的问题,为什么代码坪只有1个地址..

    while(ar.next()){ 
        try{ 
         //here, I create and start the threads 
         new Thread(new Ping(ar.getAddress())).start(); 
    

    我怀疑你ar.getAddress()总是返回相同的地址,所以你只是创建查验同一束线程地址。

  2. 这不是线程无法访问共享资源。您需要确保资源是线程安全的。

  3. 你所要做的是创建一个线程为每个平。这可能是一个糟糕的做法,特别是当你有很多地址时,因为1)线程创建可能会导致开销,2)拥有太多线程会增加资源争用。更好的方法是使用ExecutorService。它为你管理一个线程池,你所要做的就是提交任务(即ping一个地址)

+0

地址是不同的,我相信这一点。我将尝试ExecutorService。听起来像它可以解决我的问题。 – Sebowski

1

创建大量的线程可能会使性能变差。线程的最佳数量取决于许多因素,包括您的操作系统允许JVM使用多少个CPU /内核,以及线程正在执行的工作主要是CPU限制还是I/O限制。很难猜测有多少线程可以使用,但可以肯定地说254是太多了。

而是明确创建线程,饲料Runnable任务为ThreadPoolExecutor。这可以让玩家轻松使用多个线程。你甚至可能发现你的OS网络堆栈是瓶颈,并且使用多线程完全没有收获。

+0

我已经用wireshark测试过,直到现在,它一次只激活一个ping命令。所以很难判断网络堆栈是否会成为问题。 ThreadPoolExecutor听起来像一个好主意,我定义会尝试一下。但是因为我不适合编码,所以在我弄清楚如何使用这些java.util.concurrent库之前可能需要一段时间。但如果你愿意的话,我会保持你的更新。 – Sebowski

0

在icmp4j库中,我注意到在执行ping请求的同时Icmp4jUtil类的初始化期间,只有基于操作系统的本机桥的分配才成为线程安全的,并且实际的ping过程执行不是线程安全的。所以,毫无疑问,线程不能同时ping多个地址,它可以ping多个地址。