我已经编写了一个代码片段来使用JPCAP来捕获ping。我写的代码如下:
while (true) {
try {
PacketCapture m_pcap;
m_pcap = new PacketCapture();
m_pcap.open("\Device\NPF_{007262BD-....-7EE83D72EBEA}",true);//param 1 is actual device ID
m_pcap.setFilter("proto ICMP", true);
pktlistener a = new pktlistener(); //handles the packet
m_pcap.addPacketListener(a);
System.out.println("going to sleep");
Thread.sleep(1 * 1000);// Waiting for 1 second before ending capture
System.out.println("woken up");
m_pcap.removePacketListener(a);
m_pcap.endCapture();
m_pcap.close();
a = null;
m_pcap = null;
} catch (Exception e) {
e.printStackTrace();
}
}
现在上面的代码每隔一秒就开始一个新的捕获。上面的问题是,在循环运行10次之后,它抛出异常:
Exception in thread "Thread-6" java.lang.Error: Too many instances, exceeds 10
at net.sourceforge.jpcap.capture.PacketCapture.<init>(PacketCapture.java:51)
Q1。我该如何预防呢?我需要每秒启动一个新的PacketCapture。
Q2。有没有其他更简单的方法来捕获通过java在系统上接收到的ping消息?
不能使用PacketCapture
的构造函数超过10次。这种行为是硬编码的,构造函数看起来像这样:
/**
* Create a new packet capture instance.
*/
public PacketCapture() {
if (nextInstance >= INSTANCE_MAX) {
throw new Error("Too many instances, exceeds " + INSTANCE_MAX);
}
instanceNum = nextInstance++;
}
要捕获ping请求,应该尝试以下代码
public class Main {
public static void main(String[] args) throws CaptureDeviceLookupException {
Capture cap = new Capture();
cap.doCapture();
}
}
class PingListener implements PacketListener {
@Override
public void packetArrived(Packet packet) {
try {
// only ICMP packages
if (packet instanceof ICMPPacket) {
ICMPPacket tcpPacket = (ICMPPacket) packet;
int data = tcpPacket.getMessageCode();
// only echo request packages
if (data == ICMPMessages.ECHO) {
// print source and destination.
String srcHost = tcpPacket.getSourceAddress();
String dstHost = tcpPacket.getDestinationAddress();
System.out.println("Ping from: " + srcHost + " to " + dstHost);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Capture {
public void doCapture() {
// create capture instance
PacketCapture capture = new PacketCapture();
// add listener that handles incomming and outgoing packages
PingListener pingListener = new PingListener();
capture.addPacketListener(pingListener);
// m_pcap.setFilter("filter here or in handler", true);
try {
capture.open("\Device\NPF_{...}", true); // connect capture to device
while (true) {
capture.capture(1); // capture one package
}
} catch (Exception e) {
e.printStackTrace(); // exception during capture or handling of
// packages
} finally {
// technically never reached as the loop goes on forever.
// if loop terminates after a while then:
// remove listener
capture.removePacketListener(pingListener);
// end capture (only necessary, if PacketCapture still waits for
// other packages)
capture.endCapture();
// close connection to capture device
capture.close();
}
}
}
我认为对PacketCapture
类存在误解。它实际上并没有捕获一个包,然后被丢弃。它打开一个连接到你想要捕获包的设备,然后开始监听,只要你保持这个连接。然后通过调用capture.capture(n)
开始捕获n
包。当"capture"阻塞程序时,对于每个到达的包,将调用侦听器。
或者,您可以放弃while循环并使用capture.capture(-1)
。这将永远阻塞您的程序,直到您从另一个设备关闭捕获。