该示例演示了如何使用 pcap 和 Java 捕获网络数据包。
要运行示例,您将需要为操作系统安装 libpcap 。 对于 Windows,下载并安装 WinPcap 。
Ubuntu 用户可以运行以下命令来安装 libpcap:
sudo apt-get install libpcap-dev
我们将使用 jNetPcap 作为 Java 包装器。 以下示例要求版本 1.4
列出网络设备
import java.util.ArrayList;import java.util.List;import org.jnetpcap.Pcap;import org.jnetpcap.PcapIf;public class NetworkInterfaces {public static void main(String[] args) {List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICsStringBuilder errbuf = new StringBuilder(); // For any error msgsint r = Pcap.findAllDevs(alldevs, errbuf);if (r == Pcap.NOT_OK || alldevs.isEmpty()) {System.err.printf("Can't read list of devices, error is %s",errbuf.toString());return;}System.out.println("Network devices found:");int i = 0;for (PcapIf device : alldevs) {String description = (device.getDescription() != null) ? device.getDescription() : "No description available";System.out.printf("#%d: %s [%s]\n", i++, device.getName(),description);}}}
捕捉数据包
以下完整示例捕获了前 10 个数据包:
import java.util.ArrayList;import java.util.List;import org.jnetpcap.Pcap;import org.jnetpcap.PcapIf;import org.jnetpcap.packet.PcapPacket;import org.jnetpcap.packet.PcapPacketHandler;import org.jnetpcap.protocol.network.Ip4;public class PackageCapture {public static void main(String[] args) {List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICsStringBuilder errbuf = new StringBuilder(); // For any error msgsint r = Pcap.findAllDevs(alldevs, errbuf);if (r != Pcap.OK || alldevs.isEmpty()) {System.err.printf("Can't read list of devices, error is %s",errbuf.toString());return;}System.out.println("Network devices found:");int i = 0;for (PcapIf device : alldevs) {String description = (device.getDescription() != null) ? device.getDescription() : "No description available";System.out.printf("#%d: %s [%s]\n", i++, device.getName(),description);}PcapIf device = alldevs.get(0); // Get first device in listSystem.out.printf("\nChoosing '%s' on your behalf:\n",(device.getDescription() != null) ? device.getDescription(): device.getName());int snaplen = 64 * 1024; // Capture all packets, no trucationint flags = Pcap.MODE_PROMISCUOUS; // capture all packetsint timeout = 10 * 1000; // 10 seconds in millisPcap pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);if (pcap == null) {System.err.printf("Error while opening device for capture: "+ errbuf.toString());return;}PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {public void nextPacket(PcapPacket packet, String user) {byte[] data = packet.getByteArray(0, packet.size()); // the package databyte[] sIP = new byte[4];byte[] dIP = new byte[4];Ip4 ip = new Ip4();if (packet.hasHeader(ip) == false) {return; // Not IP packet}ip.source(sIP);ip.destination(dIP);/* Use jNetPcap format utilities */String sourceIP = org.jnetpcap.packet.format.FormatUtils.ip(sIP);String destinationIP = org.jnetpcap.packet.format.FormatUtils.ip(dIP);System.out.println("srcIP=" + sourceIP +" dstIP=" + destinationIP +" caplen=" + packet.getCaptureHeader().caplen());}};// capture first 10 packagespcap.loop(10, jpacketHandler, "jNetPcap");pcap.close();}}
如果要捕获特定的数据包,可以设置一个过滤器,如下所示:
PcapBpfProgram filter = new PcapBpfProgram();String expression = "tcp port 3724 or tcp port 1119";int optimize = 0; // 0 = falseint netmask = 0xFFFFFF00; // 255.255.255.0if (pcap.compile(filter, expression, optimize, netmask) != Pcap.OK) {System.err.println(pcap.getErr());return;}if (pcap.setFilter(filter) != Pcap.OK) {System.err.println(pcap.getErr());return;}
