大致原理:winpcap提供底层工具,我们只需要使用它的函数就可以编程,然而很繁琐。java就再封装一层,就出现JPcap这个中间件了。使用对比之后,JPcap尼玛不要太方便。
附:工具:winpcap要安装,这个我就不说了。JPcap作为中间件你需要下载,我没有安装。1.将JPcap.dll动态链接库加入到我的 C:\Program Files\Java\jdk1.7.0_71\jre\bin 中。2.Jpacp.jar我直接外部配置路径了。
不多说,贴可用代码
主程序类,用于读取网卡接口,并开多线程从各个网卡上读取包
package com.sock1; import java.util.Scanner; import jpcap.JpcapCaptor; import jpcap.NetworkInterface; import jpcap.PacketReceiver; import jpcap.packet.*; /** * 使用jpcap显示网络上的各种数据包 * @author www.NetJava.cn */ public class sock_main { private static int model; //程序启动主方法 public static void main(String args[]){ try{ System.out.println("请输入你需要抓取的类型包:"); System.out.println("TCP包输入‘1’"); System.out.println("UDP包输入‘2’"); System.out.println("ICMP包输入‘3’"); System.out.println("ARP包输入‘4’"); Scanner in=new Scanner(System.in); model = in.nextInt(); //获取本机上的网络接口对象数组 final NetworkInterface[] devices = JpcapCaptor.getDeviceList(); for(int i=0;i<devices.length;i++){ NetworkInterface nc=devices[i]; //创建某个卡口上的抓取对象,最大为2000个 JpcapCaptor jpcap = JpcapCaptor.openDevice(nc, 2000, true, 20); startCapThread(jpcap); //线程执行抓包 System.out.println("开始抓取第"+i+"个卡口上的数据"); } }catch(Exception ef){ ef.printStackTrace(); System.out.println("启动失败: "+ef); } } //将每个Captor放到独立线程中运行 public static void startCapThread(final JpcapCaptor jpcap ){ JpcapCaptor jp=jpcap; java.lang.Runnable rnner=new Runnable(){ //创建线程 public void run(){ //使用接包处理器循环抓包 jpcap.loopPacket(-1, new TestPacketReceiver(model)); //-1无限抓取包,抓包监听器获取包 } }; new Thread(rnner).start();//启动抓包线程 } } 抓包类,实现抓包功能,并输出信息 package com.sock1; import jpcap.PacketReceiver; import jpcap.packet.ARPPacket; import jpcap.packet.DatalinkPacket; import jpcap.packet.EthernetPacket; import jpcap.packet.ICMPPacket; import jpcap.packet.Packet; import jpcap.packet.TCPPacket; import jpcap.packet.UDPPacket; /** * 抓包监听器,实现PacketReceiver中的方法:打印出数据包说明 */ class TestPacketReceiver implements PacketReceiver { public int model; public TestPacketReceiver (int n) { this.model = n; } /** * 实现的接包方法: */ public void receivePacket(Packet packet) { //Tcp包 if(packet instanceof jpcap.packet.TCPPacket && model== 1){ TCPPacket p=(TCPPacket)packet; String s="TCPPacket:| 目的ip及端口 "+p.dst_ip+":"+p.dst_port +"|源ip及端口 "+p.src_ip+":"+p.src_port +" |数据长度: "+p.len; System.out.println(s); } //UDP包 else if(packet instanceof jpcap.packet.UDPPacket && model== 2){ UDPPacket p=(UDPPacket)packet; String s="UDPPacket:| 目的ip及端口 "+p.dst_ip+":"+p.dst_port +"||源ip及端口 "+p.src_ip+":"+p.src_port +" |数据长度: "+p.len; System.out.println(s); } //ICMPPacket包 else if(packet instanceof jpcap.packet.ICMPPacket && model== 3){ ICMPPacket p=(ICMPPacket)packet; //ICMP包的路由链 String router_ip=""; for(int i=0;i<p.router_ip.length;i++){ router_ip+=" "+p.router_ip[i].getHostAddress(); } String s="@ @ @ ICMPPacket:| 路由IP: "+router_ip +" |redir_ip: "+p.redir_ip +" |最大传输单元: "+p.mtu +" |长度: "+p.len; System.out.println(s); } //ARP请求包 else if(packet instanceof jpcap.packet.ARPPacket && model== 4){ ARPPacket p=(ARPPacket)packet; //Returns the hardware address (MAC address) of the sender Object saa= p.getSenderHardwareAddress(); Object taa=p.getTargetHardwareAddress(); String s="* * * ARPPacket:| 发送硬件地址: "+saa +"|目标硬件地址: "+taa +" |长度: "+p.len; System.out.println(s); } //取得链路层数据头 :如果你想局网抓包或伪造数据包,嘿嘿 DatalinkPacket datalink =packet.datalink; //如果是以太网包 if(datalink instanceof jpcap.packet.EthernetPacket){ EthernetPacket ep=(EthernetPacket)datalink; String s=" 以太包: " +"|目的MAC: "+ep.getDestinationAddress() +"|源MAC: "+ep.getSourceAddress(); System.out.println(s); } } }