3获取网络接口设备[网卡设备]
想要捕捉网络数据包,首先要得到你电脑了的网络接口设备,也就是所谓的网卡设备.Jpcap包向我们提供了这一个类方法[静态方
法]:JpcapCaptor.getDeviceList( ) ,从字面见就知道返回的是网络接口设备的列表,NetworkInterface类,网络接口类。其封装了相应网络设口信息,比如:网卡名,网卡描述,网卡所处的数据链路层的名称,描述等等。
简单的应用代码如下:
/**
* @(#)GetDevices.java
* 显示网络接口设备信息的Demo
* @author scholar_ii
* @version 1.00 2005/12/16
*/
import jpcap.*;
public class GetDevices
{
public GetDevices()
{
}
public static void ShowNeworkInterfaceDevices()
{
//获得网卡设备的实例列表
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//循环输出全部网卡设备对象相应的信息
for (int i = 0; i < devices.length; i++)
{ //设备号,网卡名,网卡描述
System.out.println(i+": "+devices[i].name + "(" + devices[i].description+")");
//网卡所处数据链路层的名称与其描述
System.out.println(" datalink: "+devices[i].datalink_name + "(" +
devices[i].datalink_description+")");
//网卡MAC地址
System.out.print(" MAC address:");
for (byte b : devices[i].mac_address)//JDK1.5以上版本的for语法的加强变种[循环遍历]
&nbs
欢迎光临学网,收藏本篇文章[1] [2]
$False$
p; //转化为十六进制的字串符表示
System.out.print(Integer.toHexString(b&0xff) + ":");
System.out.println(); //print out its IP address, subnet mask and broadcast address //输出网卡IP地址IPV4 IPV6 子网地址扩播地址
for (NetworkInterfaceAddress a : devices[i].addresses)
System.out.println(" address:"+a.address + " " + a.subnet + " "+ a.broadcast);} }
public static void main(String[] args) {
ShowNeworkInterfaceDevices();
}
}
可能的运行结果如下(WindowsXP下):
0: \Device\NPF_GenericDialupAdapter(Adapter for generic dialup and VPN capture)
datalink: EN10MB(Ethernet)
MAC address:0:0:0:0:0:0:
1: \Device\NPF_{B7CE211D-CEA5-4010-9A39-B833BBEC772D}(Realtek RTL8139/810x Family Fast Ethernet NIC (Microsoft''s Packet Scheduler) )
datalink: EN10MB(Ethernet)
MAC address:0:e0:4c:87:a0:5a:
address:/192.168.1.102 /255.255.255.0 /255.255.255.255
注意:0号网卡是一个操作系统的虚拟网卡(有时在上面代码前有图形界面代码如JFrame 之类的代码)可能0号网卡得不到,我的实验结果是这样的在2000下不管怎样都可以得到0与网卡,XP下有图形代码的影响就得不到了。
4 打开网络接口设备
当你得到网络接口设备列表后,你所要做的事就是打开一个网络接口设备.得到一个捕获者的实例,JpcapCaptor类的实例.如下的代码就是实现上述目的.
NetworkInterface[] devices = JpcapCaptor.openDeviceList();//获得网卡设备列表
int index = number;//设置你想要打算的网卡设备
//打开一个网络接口设备,得到一个JpcapCaptor实例
JpcapCaptor captor =
JpcapCaptor.openDevice(devices[index],65535,false,20);
openDevice方法的参数解释如下:
第一个参数类型:NetworkInterface 解释:你想要打开的网卡设备实例
第二个参数类型int 解释:一次捕捉数包的最大的字节
第三个参数类型boolean 解释:是否设置网卡为混乱模式
第四个参数类型int 解释:捕捉包的超时时间
注:JpcapCaptor实例的功能就是捕捉包.发送包并不是它的责任
5如何使用JpcapCaptor实例来捕捉网络数据包
当你通过打开网卡设备得到JpcapCaptor实例后,就可以利用它来捕捉网络数据包了。你可以利用以下两种方法来捕捉网络数据包。第一种是通过回调函数的机制,另一种是利用JpcapCaptor实例的getPacket()的方法,一个数据包一个数据包的接收。第一种是类似与
事件触发的机制。
方法一:回调函数机制。
首先,你要自定义一个类,该类必顺实现PacketReceiver接口,(在事件处理机制雷同)。PacketReciver接口只声名了receivePacket(Packet packet) 方法,所以你要在你自义的类中实现该方法,方法体里放置你处理接收到的数据包的代码,得到的数据
包为型参packet.
接着,你就可以通过调用JpcapCaptor类的实例的processPacket()或loopPacket()来开始接收数据包。开始接收数据包后,当接收到数据包时就会回调实现PacketReceiver接口的类的receivePacket的方法,使理接收到的数据包。
public int processPacket(int n , PacketRecevier handler);
参数1 类型int 解释:一次接收包的个数(个数
到时到产生回调)
参数2 类型PacketRecevier 解释:(回调者)事件临听者
返回值:捕捉到的数据包的个数
功能:捕捉自定义个数的网络数据包。与loopPacket()方法不同,当接收超时(这个由前面的openDevice()方法的最后一个接收超时参数所决定)该方法立即返回。同样的在非阻塞模式下是,没有数据
所可接收,该方法也立即返回。
public int loopPacket(int n, PacketRecevier handler):
参数1 类型int 解释:一次接收包的个数(个数
到时到产生回调)
如下为一个简单的demo:
/**
* @(#)GetPacketDemo.java
*
* 演示利用回调机制来捕捉网络数据包
* @author scholar_ii
* @version 1.00 2007/12/17 *
import jpcap.*;
import jpcap.packet.*;
public class GetPacketDemo
{
public static void main(String [] args) throws Exception
{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
int index = 0;
if(devices.length>1)/*去掉虚拟网卡的处理*/
index = 1;
JpcapCaptor captor = JpcapCaptor.openDevice(devices[index], 65535, false, 20);
captor.loopPacket(-1, new Receiver());
}
}
class Receiver implements PacketReceiver
{
/*实例receivePacket方法*/
public void receivePacket(Packet packet)
{
/*进行简单的处理*/
System.out.println(packet);
}
}
参数2 类型PacketRecevier 解释:(回调者)事件临听者
返回值:捕捉到的数据包的个数
功能:捉自定义个数的网络数据包。与processPacket()方法不同,该方法忽
视超时,不支持工作在非阻塞模式。
注意:在这两个方法的第一个参数中,你可以设定其值为-1。这时你可以停的捕捉数据包,直到捕捉结束,或错误发生为止
主要程序如下:
public class ARPMsg implements Runnable {
static JpcapCaptor captor;
static NetworkInterface[] devices;
static BufferedReader in = new BufferedReader(new InputStreamReader(
System.in));
static int i = 0;
static String str;
static IPPacket p;
static IPPacket ip;
static boolean bl = true;
public static void main(String[] args) {
System.out.println(".....ARP ....");
nic();
try {
captor = JpcapCaptor.openDevice(devices[i], 65535, false, 2000); //创建一个与指定设备的连接并返回该连接
captor.setFilter("arp", true); //过滤得到需要的ARP 包
} catch (IOException e) {
System.out.println(e.getMessage());
}
Runnable runnable = new ARPMsg();
Thread thread = new Thread(runnable); //开启一个子线程监听ARP报文
thread.setName("thread1");
thread.setPriority(6);
thread.start();
Scanner s = new Scanner(System.in); //在main线程中,,输入"exit"用于停止监听
String input = s.next();
if (input.equals("exit"))
System.exit(0); //normal exit
}
public void run() { //子线程thread1运行时调用的方法
while (bl) {
captor.processPacket(1, handler); //监听并捕获ARP包 }
}
public static int nic() {
devices = JpcapCaptor.getDeviceList(); //返回一个网络设备列表
for (int i = 0; i < devices.length; i++) { //打印可选设备的网卡信息
System.out.println(i + ". > " + "NIO_gen_eth: " + devices[i].name); for (NetworkInterfaceAddress a : devices[i].addresses) {
System.out.println(" IP address:" + a.address);
}
}
System.out.print("> Choose the NIC you want to use: ");
try {
str = in.readLine(); //输入数字并选择网卡 } catch (IOException e) {
System.out.println(e.getMessage());
}
i = Integer.parseInt(str);
return i;
}
private static PacketReceiver handler = new PacketReceiver() {
public void receivePacket(Packet packet) { //匿名类,每捕获一个包就调用此方法
System.out.println("===================================");
if(Short.valueOf(ARPPacket.ARP_REQUEST).equals(((ARPPacket) packet) .opration))
{
System.out.println("This is arp request message");
}
if(Short.valueOf(ARPPacket.ARP_REPLY).equals(((ARPPacket) packet).o peration))
{
System.out.println("This is arp reply message");
}
System.out.println("硬件类型" + ((ARPPacket) packet).hardtype);
System.out.println("操作类型" + ((ARPPacket) packet).operation); System.out.println("源MAC地址
" + ((ARPPacket) packet).getSenderHardwareAddress());
System.out.println("源IP地
址" + ((ARPPacket) packet).getSenderProtocolAddress());
System.out.println("目标MAC地
址" + ((ARPPacket) packet).getTargetHardwareAddress());
System.out.println("目标IP地
址" + ((ARPPacket) packet).getTargetProtocolAddress());
System.out.println("===================================");
}
};
}
本程序采用多线程的实现对ARP数据包进行监听并捕获,首先
JpcapCaptor.getDeviceList()获得可用的设备,并输出以供用户选择,当用户选择并输入可用的设备号后,JpcapCaptor.openDevice()创建一个与所选设备的连接,false参数表示启用混杂模式,captor.setFilter("arp",true)过滤得到ARP数据包,这时开启一个叫做JARP的
子线程,运行captor.processPacket(1, handler)方法用于捕获ARP数据包,一旦ARP数据包出现,交由PacketReceiver接口的唯一实现方法receivePacket()来处理。与此同时,在另外一个main线程中,通过new Scanner(System.in)来指定当输入字符"exit"时,程序退出。之所以在main线程而不是在子线程来指定输入的字符"exit",是因为System.in是一个阻塞函数,若在子线程中会阻断子线程监听捕获ARP数据包。