您的位置:首页 > 其它

学习使用Jpcap抓取数据包过程中的一些记录和问题

2013-03-29 09:50 597 查看
1. Jpcap
Jpcap是一个基于Java主要用来捕获网络数据包并进行处理的中间件,通过调用外部动态链接库(Windows下.dll,
Linux下 .so)的形式弥补了Java不能处理数据链路层的缺陷。
2. 环境搭建
http://jpcap.sourceforge.net/下载最新
Jpcap 打包资源

Window jpcap-x.xx.xx-win32.zip
Linux jpcap-x.xx.xx.tar.gz
(x.xx.xx为版本号,具体参考官网)

以下环境在Window系统上搭建
1)把资源包下 lib/jpcab.dll文件拷贝到当前编译环境的jre/bin目录下。

PS:使用 myEclipse作为IDE的同学如果没有设置本地JDK路径会默认在myEclipse安装的同级路径下生成AppData文件夹,以下是我的当前
jre 路径
G:\AppData\Local\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre

2)资源包下 jars/ net.sourceforge.jpcap-x.xx.xx.jar添加到项目的Reference Libraries里
或者将路径添加到classPath里。Jars/javadoc_net.sourceforge.jpcap-x.xx.xx.jar为Jpcap的API开发文档。
3.
案例

以下是Jpcap官方给出的第一个例子

import net.sourceforge.jpcap.capture.*;

import net.sourceforge.jpcap.net.*;

public classExample1

{

privatestaticfinal intINFINITE = -1;

privatestaticfinal intPACKET_COUNT = 10;

//BPF filter for capturing any packet

privatestaticfinal StringFILTER =  "";

privatePacket Capturem_pcap;

private Stringm_device;

publicExample1()throws Exception {

//Step 1: Instantiate Capturing Engine

m_pcap =newPacketCapture();

//Step 2:  Check for devices

// 此处官方的例子给出的是m_device = m_pcap.findDevice();经过测试,得到两个结果:

// 1)findDevice()方法取到的device的名字额外包括了适配器具体的名字

//   以下是我输出的结果:

//   \Device\NPF_{EB07CCEA-BFDC-4438-B73D-AB507CFDF470}

//   BroadcomNetLink (TM) Gigabit Ethernet Driver

//   红字部分才是 device需要的名字,多出来适配器的名字后,在接下来用open()调用动态链

//   接库的时候会报CaptureDeviceOpenException:Erroropening adapter异常

//    所以我用subString取了前面有效的部分正好是50个字符,具体的PC也许需要具体测试。

// 2)由于我的本机有包括虚拟网卡在内的共5个网卡适配器,findDevice()默认只取了第一个适

//     配器,并不是那个连着外网的适配器,所以抓不到何与外网交互产生的数据包,于是我用

//     PacketCapture.lookupDevices()取得了所有可用的device,然后挨个测试,确定了

//     第4个device就是那个产生多数据包的适配器,同样,这个参数也需要具体测试。

m_device  = PacketCapture.lookupDevices()[4].substring(0, 50);

//Step 3: Open Device for Capturing(requires root)

m_pcap.open(m_device,false);

//Step 4: Add a BPF Filter (seetcpdumpdocumentation)

m_pcap.setFilter(FILTER,true);

//Step 5: Register a Listener for RawPackets

m_pcap.addRawPacketListener(newRawPacketHandler());

// Step 6:  Capture Data (max. PACKET_COUNT packets)

// 这里的参数表示具体指定捕获多少个包,设为-1时将会一直捕获直到报错或程序退出

m_pcap.capture(PACKET_COUNT);

}

publicstaticvoid main(String[] args) {

try {

Example1 example = new Example1();

} catch(Exceptione) {

e.printStackTrace();

System.exit(1);

}

}

}

class RawPacketHandlerimplementsRawPacketListener

{

privatestaticintm_counter = 0;

publicvoidrawPacketArrived(RawPacket data) {

m_counter++;

System.out.println("Receivedpacket (" +m_counter +")");

}

}


之后我重新写了这个捕获包的监听器为了只抓TCP的包
先把 Step5替换成
m_pcap.addPacketListener(newTcpPacketHandler());

接下来改了原来那个RawPacketHandler类
class TcpPacketHandlerimplementsPacketListener {

@Override

publicvoidpacketArrived(Packet packet) {

try {

//only handle TCP packets

if(packetinstanceofTCPPacket) {

TCPPacket tcpPacket = (TCPPacket) packet;

byte[] data= tcpPacket.getTCPData();

StringsrcHost = tcpPacket.getSourceAddress();

StringdstHost = tcpPacket.getDestinationAddress();

StringisoData = new String(data,"ISO-8859-1");

System.out.println(srcHost+" -> " + dstHost +":" + isoData);

}

} catch(Exception e) {

e.printStackTrace();

}

}

}


在我运行后发现一个TCP包都捕获不到。
于是我用System.out.println(packet.getClass().getName());打印了所有捕获的
包的类型

结果如下图:



从中发现,捕获到最多的包是EthernetPackage,然后少数的IPPackage和ARPPackage

研究猜测了一种可能,就是网络层的许多包(包括TCP/UDP)在以太网上传输的时候被封装成了以太包。

具体得到其中TCPPacket的办法还在寻找,有知道的请指教一下,拜谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: