我使用 jnetpcap 库来监听网络流量,基本上使用 PcapPacketHandlers 来监听数据包,在初始化它们之后,我启动一个 pcap.loop() 方法,这样它就会开始监听。 然而,当我运行我的程序时,大约有 50% 的时间循环不会启动,程序会卡住,没有错误,没有异常。我只得到 1 个打印输出,仅此打印输出:loop1DEVICES CHOSEN: \Device\NPF_{0A6670EB-FED6-4AD0-9EE6-1F9BA35A75A5},\Device\NPF_{E0FB8017-9FFB-4489-A894-8D256394087C} IP:[已删除] 应该是:192.168.1.2 IP:[已删除] 应该是:147.66.12.4 开始 ... 真正的开始 Loop1 现在应该开始了: Loop2 现在应该开始了:
这是代码:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapBpfProgram;
import org.jnetpcap.PcapDumper;
import org.jnetpcap.PcapIf;
import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.protocol.network.Ip4;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.awt.desktop.AppEvent;
import java.io.IOException;
import java.net.*;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Switch extends Application
{
private int pcn1=0;
private int pcn2=0;
private int counter =0;
private Map<String, ScheduledExecutorService> pingThreads;
public static ArrayList<String> devices;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
PcapPacketHashTable packetTable = PcapPacketHashTable.getInstance();
@Override
public void start(Stage primaryStage) throws Exception {
//GUI SETUP
FXMLLoader loader = new FXMLLoader(getClass().getResource("GUI.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Network Traffic");
primaryStage.setScene(new Scene(root, 835, 1000));
primaryStage.show();
//Switch setup
SwitchMacTable macT= SwitchMacTable.getInstance();
Port p1= new Port(null,null,"Fa0/",null,null,macT);
Port p2= new Port(null,null,"Fa0/",null,null,macT);
Packet statisticsInPort1 = new Packet();
Packet statisticsOutPort1 = new Packet();
Packet statisticsInPort2 = new Packet();
Packet statisticsOutPort2 = new Packet();
p1.setIn(statisticsInPort1);
p1.setOut(statisticsOutPort2);
p2.setIn(statisticsInPort2);
p2.setOut(statisticsOutPort1);
// packet sniffer
int snaplen = 64 * 1024;
int flags = Pcap.MODE_PROMISCUOUS;
int timeout = 1000; // 10ms
int opt = 0;
int mask = 0xffffff00;
//start GUI
GUI gui= loader.getController();
gui.initialize(p1,p2);
devices = new ArrayList<String>();
List devicelist = new ArrayList();
List<PcapIf> tempdevices = new ArrayList<PcapIf>();
StringBuilder errbuf = new StringBuilder();
String err = "";
//nacitanie sietovych zariadeni
int foundd = Pcap.findAllDevs(devicelist, errbuf);
if (foundd != Pcap.OK) {
System.err.printf("Can't read list of devices, error is %s", errbuf.toString());
return;
}
for (Object dev : devicelist) {
tempdevices.add((PcapIf) dev);
devices.add(dev.toString());
}
System.out.println(tempdevices.size() + " network devices found:");
int i = 0;
ArrayList<String> dvar = new ArrayList<>();
for (PcapIf device : tempdevices) {
String description = (device.getDescription() != null) ? device.getDescription() : "No description available";
dvar.add(description);
}
gui.addCombos(dvar);
new Thread(() -> {
while (true) {
int iiii = 1;
int b=5;
int yt=iiii+b;
System.out.print("smp");
try {
while(p1.getStop()==0) {
System.out.print("loop2");
while (p1.getStart() == 0) {
//waiting for adapter choice.
int ii = 1;int bbb=5;
int yttt=iiii+bbb;
System.out.print("loop1");
}
PcapIf device = tempdevices.get(gui.getAdapterC1());
Thread.sleep(1000);
PcapIf device2 = tempdevices.get(gui.getAdapterC2());
Thread.sleep(1000);
byte[] ar = device.getHardwareAddress();
byte[] ar2 = device2.getHardwareAddress();
Packet np = new Packet();
String devname1 = device.getName();
String devname2 = device2.getName();
System.out.println("DEVICES CHOSEN: " + devname1 + "," + devname2);
InetAddress adaIp1=null;
InetAddress adaIp2=null;
if (ar != null) {
System.out.println("IP: "+device.getAddresses().get(0).getAddr());
byte[] adapip = device.getAddresses().get(0).getAddr().getData();
try {
adaIp1 = InetAddress.getByAddress(adapip);
System.out.println("THS SHOULD BE IT : "+ adaIp1.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
System.exit(0);
}
}
if (ar2 != null) {
System.out.println("IP: "+device2.getAddresses().get(0).getAddr());
byte[] adapip = device2.getAddresses().get(0).getAddr().getData();
try {
adaIp2 = InetAddress.getByAddress(adapip);
System.out.println("THS SHOULD BE IT : "+ adaIp2.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
System.exit(0);
}
}
//Open the selected device to capture packets
Pcap pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);
Thread.sleep(1000);
Pcap pcap2 = Pcap.openLive(device2.getName(), snaplen, flags, timeout, errbuf);
Thread.sleep(1000);
if (pcap == null || pcap2 == null) {
if (pcap == null) {
System.err.printf("Error while opening device for capture: " + errbuf.toString());
} else {
System.err.printf("Error while opening device for capture: " + errbuf.toString());
}
return;
}
PcapBpfProgram program = new PcapBpfProgram();
String filter = "ether proto \\ip or arp or udp or tcp or icmp or (tcp port 80) or (tcp port 443)";
if (pcap.compile(program, filter, opt, mask) != Pcap.OK) {
System.out.println(pcap.getErr());
return;
}
if (pcap.setFilter(program) != Pcap.OK) {
System.out.println(pcap.getErr());
return;
}
if (pcap2.compile(program, filter, opt, mask) != Pcap.OK) {
System.out.println(pcap2.getErr());
return;
}
if (pcap2.setFilter(program) != Pcap.OK) {
System.out.println(pcap2.getErr());
return;
}
System.out.println("start ...");
p1.setInterfaceName(devname1);
p2.setInterfaceName(devname2);
p1.setPcap(pcap);
p2.setPcap(pcap2);
PingThread pt1 = new PingThread(null,adaIp1,macT,null);
PingThread pt2 = new PingThread(null,adaIp2,macT,null);
byte[] adapterMacAddress = device.getHardwareAddress();
byte[] adapter2MacAddress = device2.getHardwareAddress();
System.out.println("Real start");
// LOOP 1 1 1 1 1 LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOP
PcapPacketHandler<String> port1 = (packet, user) -> {
System.out.println("PICSA");
if (1 == 1) {
if((Arrays.equals(packet.getByteArray(6, 6), adapterMacAddress)) || (Arrays.equals(packet.getByteArray(6, 6), adapter2MacAddress)))
{
System.out.println("ret1 + " + p1.getIn().bytesToHexString(packet.getByteArray(0, 6)));
return ;
}
System.out.println("p total size: "+ packet.getTotalSize() + " size: "+ packet.size());
if (packetTable.contains(packet)) {
System.out.println("REMOVING PACKET");
packetTable.remove(packet);
return;
}
ArrayList<String> ars = p1.getIn().categorize(packet);
String destIP = ars.get(0);
String srcIP = ars.get(1);
String maca = ars.get(2);
//ICMP PING NOT YET IGNORED, DO IT NEXT TIME !!!!
macT.addToMacTable(packet, 1, p1); //addmac,refrespack1,setbytepack,sendpcap,categ2,refresh2
Platform.runLater(() -> {
gui.refresh(macT.getMacAddress());
});
packetTable.put(packet);
pcap2.sendPacket(packet);
p1.getOut().categorize(packet);
System.out.println("pack sent");
Platform.runLater(() -> {
gui.refreshPacketCounters(p1.getIn().getChange(), 0);
gui.refreshPacketCounters(p1.getOut().getChange(), 2);
});
// PingThread.startPingThread(srcIP, pt1.getSourceAddresss(), pt1.getSmts(), maca);
}
}
;
// LOOP 2 2 222 LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOP
PcapPacketHandler<String> port2 = (packet, user) -> {
System.out.println("picsa2");
if (1 == 1) {
if((Arrays.equals(packet.getByteArray(6, 6), adapterMacAddress)) || (Arrays.equals(packet.getByteArray(6, 6), adapter2MacAddress)))
{ System.out.println("ret2 + " + p1.getIn().bytesToHexString(packet.getByteArray(0, 6))) ;
return ;
}
if ( packetTable.contains(packet)) {
System.out.println("REMOVING PACKET");
packetTable.remove(packet);
return ;
}
System.out.println("GOTR PACK ///////////////////////////////////////");
ArrayList<String> ars = p2.getIn().categorize(packet);
String destIP = ars.get(0);
String srcIP = ars.get(1);
String maca= ars.get(2);
macT.addToMacTable(packet, 2, p2);
System.out.println(p1.getIn().bytesToHexString(adapter2MacAddress) + " or "+ adapter2MacAddress);
// Platform.runLater(() -> {
// gui.refresh(macT.getMacAddress());
//});
Platform.runLater(() -> {
gui.refresh(macT.getMacAddress());
});
int packetH = packet.hashCode();
packetTable.put( packet);
pcap.sendPacket(packet);
p2.getOut().categorize(packet);
Platform.runLater(() -> {
gui.refreshPacketCounters(p2.getIn().getChange(), 1);
gui.refreshPacketCounters(p2.getOut().getChange(), 3);
});
//PingThread.startPingThread(srcIP, pt2.getSourceAddresss(),pt2.getSmts());
}
}
;
System.out.println("Loop1 should start now :");
new Thread(() -> {
pcap.loop(Pcap.LOOP_INFINITE, port1, "pcap1");
}).start();
System.out.println("Loop2 should start now :");
pcap2.loop(Pcap.LOOP_INFINITE, port2,"pcap2");
}
} catch (Exception e) {
System.out.println("WTF?");
e.printStackTrace();
}
}
}).start();
}
我尝试了一切,但我已经没有办法理解这个错误的原因了。
几个建议。尝试检查两个 pcap.loop() 调用返回的错误代码:
System.out.println("Loop1 should start now :");
new Thread(() -> {
int result = pcap.loop(Pcap.LOOP_INFINITE, port1, "pcap1");
if (result < 0)
System.out.println(pcap.getErr());
}).start();
System.out.println("Loop2 should start now :");
int result = pcap2.loop(Pcap.LOOP_INFINITE, port2,"pcap2");
if (result < 0)
System.out.println(pcap.getErr());
其次,如果可能,请迁移到jNetpcap v2。它得到了全面的支持,目前运行良好。但是,它至少需要 JDK19,因为它使用了在 JDK19/20 中仍处于预览状态的外部函数功能。