Java 局域网流量统计

 

这里主要介绍以下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;
      }
      

你可能感兴趣的:(Java 局域网流量统计)