这里主要介绍以下JPCAP
Jpcap是2003年日本开发的一套能够捕获、发送网络数据包的java类库。因为核心Java API不能访问底层的网络数据,但Jpcap是一种提供在Windows或UNIX系统上进行这种访问的Java API。Jpcap不是一种纯粹的Java解决方案,它依赖本地库的使用。在Windows 或 UNIX上,你必须有必要的第三方库,分别是WinPcap或libpcap。要在java中使用Jpcap类库需要安装Jpcap的运行和开发环境。
Jpcap的主要功能
Jpcap提供了十分方便的数据包捕获方法。Jpcap使用一个事件模型来处理包。首先,必须创建一个执行接口jpcap.JpcapHandler的类。
public class Jpcaphandler implements JpcapHandler {
public void handlePacket(Packet packet){
System.out.println(packet);
}
}
为了捕获包,需要让Jpcap知道要用哪个网络设备来监听。API提供了jpcap.Jpcap.getDeviceList()方法以满足这一目的。这个方法返回一列字符串,可以按一下方法如下使用它:
String[] devices = Jpcap.getDeviceList();
一旦有了一个设备名称的目录,只要从其中选取一个用来监听:
String deviceName = devices[0];
选择一个设备之后,通过Jpcap.openDevice()方法打开它。openDevice()方法需要四个参数:即将打开的设备名,从设备上一次读取的最大字节数,说明是否将设备设为混杂模式的Boolean值,和以后调用processPacket()方法要使用到的超时值。
Jpcapjpcap = Jpcap.openDevice(deviceName, 1024, false, 10000);
openDevice()方法将一个参数返回到用以捕获的Jpcap对象。既然有了Jpcap实例,你可以调用processPacket() 或loopPacket()开始监听了。这两种方式都带有两个参数:捕获的最大包数可以是-1(说明没有限制);执行JpcapHandler的一个类的实例。
如果你调用processPacket(),那么Jpcap将一直捕获包,直到超过openDevice中规定的时限或达到了规定的最大包数。loopPacket()则将一直捕获包,直到达到最大包数,如果没有最大数限制,它将永远运行下去。就像下面这样调用:
jpcap.loopPacket(-1, new Jpcaphandler());
对于捕获的数据包,可以利用Jpcap中的Packet及其子类进行分类分析,获得数据包的详细信息。
Jpcap还有进行数据包过滤的函数setFilter(java.lang.String condition, boolean optimize
)。其中condition是过滤条件。在进行数据包捕获前设置过滤条件,可以将不感兴趣的数据包剔除。
jpcap.setFilter("host 210.212.147.149",true);
因为Jpcap对数据包进行了分类,而数据包中的关键字段也有接口调用,所以在设置过滤条件时也可以在利用这些条件进行更细致的分类。这将在后面的章节中介绍。
Jpcap还提供了用来发送数据包的一个类JpcapSender,可以用来发送IPPacket及其子类,包括IPPacket、ICMPPacket、TCPPacket、UDPPacket。定义好一个相应的包后,就可以利用sendPacket函数发送数据包。
JpcapSendersender=JpcapSender.openDevice(Jpcap. ()[0]);
sender.sendPacket(p); //send a packet
上面是对JPCAP的基本介绍。这是这个程序的基础。
要想了解更多有关JPCAP的有关内容请访问http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/index.html
下面是我的源代码,可以作为参考例子:
有3个文件TrafficStatistics.java getPacket.java LoopPacketThread.java
**************************************************************************************************
文件1:TrafficStatistics.java
**************************************************************************************************
package com.zhangzhen.cmd;
import java.io.IOException;
import jpcap.JpcapCaptor;
import jpcap.NetworkInterface;
import jpcap.NetworkInterfaceAddress;
public class TrafficStatistics implements Runnable
{
private String []ipAddr=new String[10];//存储本机网卡ip地址
private int ipcount = 0;//本机网卡ip地址数
public TrafficStatistics()
{
for(int i=0 ; i < ipAddr.length ; i++)
{
ipAddr[i] = new String();
}
}
//实现run方法
public void run()
{
//获得网络设备列表
NetworkInterface [] devices = JpcapCaptor.getDeviceList();
NetworkInterface ni=null;
JpcapCaptor jpcap;
for(int i = 0 ; i < devices.length ; i++)
{
ni = devices[i];
for(int j = 0 ; j < ni.addresses.length ; j++)
{
//一个网卡可能有多个地址,获得本机IP地址
ipAddr[j] = ni.addresses[j].address.toString();
ipcount++;
}
//创建卡口上的抓取对象
try
{
jpcap = JpcapCaptor.openDevice(ni, 65535, true, 20);
//创建对应的抓取线程并启动
Runnable lpt = new LoopPacketThread(jpcap , ipAddr , ipcount);
Thread lptThread = new Thread(lpt);
lptThread.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
*************************************************************************************************
文件2: getPacket.java
*************************************************************************************************
package com.zhangzhen.cmd;
import java.util.ArrayList;
import jpcap.JpcapCaptor;
import jpcap.PacketReceiver;
import jpcap.packet.ARPPacket;
import jpcap.packet.ICMPPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.Packet;
import jpcap.packet.TCPPacket;
import jpcap.packet.UDPPacket;
public class getPacket implements PacketReceiver
{
String[] ipAddr;//本机ip地址数组
int ipcount;//本机ip地址数
private int upLoadPacketSize=0;//上传数据包总字节数
private int downLoadPacketSize=0;//下载数据包总字节数
private int upLoadIPPacketSize = 0;//上传IP数据包总字节数
private int downLoadIPPacketSize = 0;//下载IP数据包总字节数
private int upLoadTCPPacketSize = 0 ; //上传TCP数据包总字节数
private int downLoadTCPPacketSize = 0 ; //下载TCP数据包总字节数
private int upLoadUDPPacketSize = 0 ; //上传UDP数据包总字节数
private int downLoadUDPPacketSize = 0 ; //下载UDP数据包总字节数
private static Packet currentPacket = new Packet();//表示最新抓取的包
public int getupLoadPacketSize()
{
return upLoadPacketSize;
}
public int getdownLoadPacketSize()
{
return downLoadPacketSize;
}
public int getupLoadIPPacketSize()
{
return upLoadIPPacketSize;
}
public int getdownLoadIPPacketSize()
{
return downLoadIPPacketSize;
}
public int getupLoadTCPPacketSize()
{
return upLoadTCPPacketSize;
}
public int getdownLoadTCPPacketSize()
{
return downLoadTCPPacketSize;
}
public int getupLoadUDPPacketSize()
{
return upLoadUDPPacketSize;
}
public int getdownLoadUDPPacketSize()
{
return downLoadUDPPacketSize;
}
public getPacket()
{
//空实现
}
public getPacket(String[]ipAddr,int ipcount)
{
this.ipAddr=ipAddr;
this.ipcount = ipcount;
}
//判断当前抓的包是否为空,若为空则表示断网,否则没断网
public static boolean isPacketEmpty()
{
if(currentPacket== null)
{
return true;
}
else
{
return false;
}
}
//获得截取的数据包
public void receivePacket(Packet p)
{
//currentPacket=null;
if(p instanceof TCPPacket)
{//如果截取的是TCP包
TCPPacket tcp = (TCPPacket)p;
if(tcp.src_ip.getHostAddress().equals(ipAddr[0].substring(1)))
{//如果TCP包的源IP地址等于本机ip则此包为上传包
upLoadTCPPacketSize+=tcp.len;
upLoadPacketSize+=tcp.len;
}
else if(tcp.dst_ip.getHostAddress().equals(ipAddr[0].substring(1)))
{//如果TCP包的目的IP地址等于本机ip则此包为下载包
downLoadTCPPacketSize+=tcp.len;
downLoadPacketSize+=tcp.len;
}
}
if(p instanceof UDPPacket)
{//如果截取的是UDP包
UDPPacket udp = (UDPPacket)p;
if(udp.src_ip.getHostAddress().equals(ipAddr[0].substring(1)))
{//如果UDP包的源IP地址等于本机ip则此包为上传包
upLoadUDPPacketSize+=udp.len;
upLoadPacketSize+=udp.len;
}
else if(udp.dst_ip.getHostAddress().equals(ipAddr[0].substring(1)))
{//如果UDP包的目的IP地址等于本机ip则此包为下载包
downLoadUDPPacketSize+=udp.len;
downLoadPacketSize+=udp.len;
}
}
if(p instanceof IPPacket)
{//如果截取的是IP包
IPPacket ippacket = (IPPacket)p;
if(ippacket.src_ip.getHostAddress().equals(ipAddr[0].substring(1)))
{//如果IP包的源IP地址等于本机ip则此包为上传包
upLoadIPPacketSize += ippacket.len;
upLoadPacketSize += ippacket.len;
}