前言
pcap/.cap文件是常用的数据报存储格式文件,数据按照特定格式存储,普通编辑器无法正常打开该类型文件,使用Ultra Edit编辑器能够以16进制的格式查看数据,无法直观查看数据重要信息。需要特定的解析工具软件读取查看如WiresharkPortable或Microsoft Network Monitor等。
问题
然而一些开发任务需要数据文件(.pcap/.cap)某项信息进行后续处理,无法使用软件获取信息输入到程序中,对开发任务带来一些困难。
解决
引入pcap4j库,该库通过网络接口捕获数据包并将它们转换为 Java 对象。可以通过从数据包转换而来的 Java 对象来获取/设置数据包头的每个字段。您还可以从头开始制作数据包对象。pcap4j还具有更强大的功能,有兴趣可关注微信公众号:Java烂笔头,回复:pcap4j-1,查看完整源码及说明。
示例代码
maven 依赖
<dependencies>
<dependency>
<groupId>org.pcap4j</groupId>
<artifactId>pcap4j-core</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.pcap4j</groupId>
<artifactId>pcap4j-packetfactory-static</artifactId>
<version>1.8.2</version>
</dependency>
</dependencies>
package org.pcap4j.sample;
import java.io.EOFException;
import java.util.concurrent.TimeoutException;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapHandle.TimestampPrecision;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.Packet;
@SuppressWarnings("javadoc")
public class ReadPacketFile {
private static final int COUNT = 5;
private static final String PCAP_FILE_KEY = ReadPacketFile.class.getName() + ".pcapFile";
private static final String PCAP_FILE =
System.getProperty(PCAP_FILE_KEY, "src/main/resources/echoAndEchoReply.pcap");
private ReadPacketFile() {}
public static void main(String[] args) throws PcapNativeException, NotOpenException {
PcapHandle handle;
try {
handle = Pcaps.openOffline(PCAP_FILE, TimestampPrecision.NANO);
} catch (PcapNativeException e) {
handle = Pcaps.openOffline(PCAP_FILE);
}
for (int i = 0; i < COUNT; i++) {
try {
Packet packet = handle.getNextPacketEx();
System.out.println(handle.getTimestamp());
System.out.println(packet);
} catch (TimeoutException e) {
} catch (EOFException e) {
System.out.println("EOF");
break;
}
}
handle.close();
}
}
2012-09-12 13:27:27.609228
[Ethernet Header (14 bytes)]
Destination address: 00:01:8e:f9:a7:60
Source address: 04:7d:7b:4c:2f:0a
Type: 0x0800 (IPv4)
[IPv4 Header (20 bytes)]
Version: 4 (IPv4)
IHL: 5 (20 [bytes])
TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
Total length: 60 [bytes]
Identification: 18814
Flags: (Reserved, Don't Fragment, More Fragment) = (false, false, false)
Fragment offset: 0 (0 [bytes])
TTL: 128
Protocol: 1 (ICMPv4)
Header checksum: 0x0000
Source address: /192.168.2.101
Destination address: /192.168.2.1
[ICMPv4 Common Header (4 bytes)]
Type: 8 (Echo)
Code: 0 (No Code)
Checksum: 0x4c5b
[ICMPv4 Echo Header (4 bytes)]
Identifier: 256
SequenceNumber: 1
[data (32 bytes)]
Hex stream: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69
2012-09-12 13:27:27.609965
[Ethernet Header (14 bytes)]
Destination address: 04:7d:7b:4c:2f:0a
Source address: 00:01:8e:f9:a7:60
Type: 0x0800 (IPv4)
[IPv4 Header (20 bytes)]
Version: 4 (IPv4)
IHL: 5 (20 [bytes])
TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
Total length: 60 [bytes]
Identification: 30935
Flags: (Reserved, Don't Fragment, More Fragment) = (false, false, false)
Fragment offset: 0 (0 [bytes])
TTL: 64
Protocol: 1 (ICMPv4)
Header checksum: 0x7c33
Source address: /192.168.2.1
Destination address: /192.168.2.101
[ICMPv4 Common Header (4 bytes)]
Type: 0 (Echo Reply)
Code: 0 (No Code)
Checksum: 0x545b
[ICMPv4 Echo Reply Header (4 bytes)]
Identifier: 256
SequenceNumber: 1
[data (32 bytes)]
Hex stream: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69
2012-09-12 13:27:28.611932
[Ethernet Header (14 bytes)]
Destination address: 00:01:8e:f9:a7:60
Source address: 04:7d:7b:4c:2f:0a
Type: 0x0800 (IPv4)
[IPv4 Header (20 bytes)]
Version: 4 (IPv4)
IHL: 5 (20 [bytes])
TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
Total length: 60 [bytes]
Identification: 18815
Flags: (Reserved, Don't Fragment, More Fragment) = (false, false, false)
Fragment offset: 0 (0 [bytes])
TTL: 128
Protocol: 1 (ICMPv4)
Header checksum: 0x0000
Source address: /192.168.2.101
Destination address: /192.168.2.1
[ICMPv4 Common Header (4 bytes)]
Type: 8 (Echo)
Code: 0 (No Code)
Checksum: 0x4c5a
[ICMPv4 Echo Header (4 bytes)]
Identifier: 256
SequenceNumber: 2
[data (32 bytes)]
Hex stream: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69
2012-09-12 13:27:28.61251
[Ethernet Header (14 bytes)]
Destination address: 04:7d:7b:4c:2f:0a
Source address: 00:01:8e:f9:a7:60
Type: 0x0800 (IPv4)
[IPv4 Header (20 bytes)]
Version: 4 (IPv4)
IHL: 5 (20 [bytes])
TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
Total length: 60 [bytes]
Identification: 30936
Flags: (Reserved, Don't Fragment, More Fragment) = (false, false, false)
Fragment offset: 0 (0 [bytes])
TTL: 64
Protocol: 1 (ICMPv4)
Header checksum: 0x7c32
Source address: /192.168.2.1
Destination address: /192.168.2.101
[ICMPv4 Common Header (4 bytes)]
Type: 0 (Echo Reply)
Code: 0 (No Code)
Checksum: 0x545a
[ICMPv4 Echo Reply Header (4 bytes)]
Identifier: 256
SequenceNumber: 2
[data (32 bytes)]
Hex stream: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69
2012-09-12 13:27:29.611909
[Ethernet Header (14 bytes)]
Destination address: 00:01:8e:f9:a7:60
Source address: 04:7d:7b:4c:2f:0a
Type: 0x0800 (IPv4)
[IPv4 Header (20 bytes)]
Version: 4 (IPv4)
IHL: 5 (20 [bytes])
TOS: [precedence: 0 (Routine)] [tos: 0 (Default)] [mbz: 0]
Total length: 60 [bytes]
Identification: 18816
Flags: (Reserved, Don't Fragment, More Fragment) = (false, false, false)
Fragment offset: 0 (0 [bytes])
TTL: 128
Protocol: 1 (ICMPv4)
Header checksum: 0x0000
Source address: /192.168.2.101
Destination address: /192.168.2.1
[ICMPv4 Common Header (4 bytes)]
Type: 8 (Echo)
Code: 0 (No Code)
Checksum: 0x4c59
[ICMPv4 Echo Header (4 bytes)]
Identifier: 256
SequenceNumber: 3
[data (32 bytes)]
Hex stream: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69
完整源码
示例源码关注微信公众号:Java烂笔头,回复:pcap4j
应用场景
需求:当数据块比较大时,数据块会被压缩,当需要通过抓包来查看数据包内容时,无法直接通过软件查看。给实际工程问题排查带来不便,需要开发一个工具,判断数据是否被压缩,如果压缩进行解压。
功能:解析报文,报文协议如下:提取出压缩的报文,并解压其中的数据,输出解压后的二进制数据。
输入:抓取的设备的报文文件。
输出:将解压的二进制数据输出。
格式:
时间:
源ip:
宿ip:
数据:
思路:通过pcap4j解析库可以直接读取每条数据的时间、源地址、宿地址、十六进制数据,其次通过Microsoft Network Monitor软件查看报文数据,找出表示是否压缩的十六进制数据位,找出每条数据的表示压缩位的位置规律,将该位转为二进制的最后一位表示是否压缩,1表示压缩,0表示未压缩。然后将压缩的数据转为二进制输出即可。
此处源码不便展示,如果需要可关注并私信微信公众号:Java烂笔头