我正在用 Java 编写一个简单的网络监控工具。它基本上只需要 ping 一个可变地址范围并将答案保存在数据库中。
起初,我使用了java.net库,但由于它只使用echo命令,打印机、路由器和网络中的一些服务器不会应答。所以我用了icmp4j图书馆。
由于 ping 254 地址范围大约需要 10 到 15 分钟,所以在逐一执行时,我决定使用线程来将扫描时间保持在最低限度。然而问题是,它一次仍然只能 ping 通一个地址。
我以前从未使用过线程,所以这里是代码,以防万一我犯了一个巨大的错误:
//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());
}
这是我的 Ping 类:
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-时,线程是同时处理的。我读过,线程不应该访问相同的资源,所以我想,这就是这里发生的事情。但我缺乏经验,无法分析甚至重写库。
这是我的 Ping 类,没有使用 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) {}
}
}
所以我想问,如果我犯了一个错误,或者是否有人有使用所述库的经验并且知道如何解决该问题或有一个好的替代方案,这就可以完成工作。
最佳答案
回答您的问题:为什么代码仅 ping 1 个地址。
while(ar.next()){ try{ //here, I create and start the threads new Thread(new Ping(ar.getAddress())).start();
我怀疑您的
ar.getAddress()
总是返回相同的地址,因此您只是创建了一堆 ping 相同地址的线程。并不是线程无法访问共享资源。您需要确保资源是线程安全的。
您想要做的是为每个单独的 ping 创建一个线程。这可能是一个不好的做法,尤其是当您有很多地址时,因为 1) 线程创建可能会导致开销,2) 线程太多会增加资源争用。更好的方法是使用 ExecutorService。它为你管理一个线程池,你所要做的就是提交任务(也就是 ping 一个地址)
关于Java:线程不会同时 ping,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32264596/