使用JPcap可以发包,使用JnetPcap可以接收和过滤包。现在项目中遇到的问题总结如下。
如果是在Window下则必须在path路径下存在JnetPcap.dll和Jpcap.dll文件,如果是在linux环境下,可以将JnetPcap.so和JnetPcap.so存放到/usr/lib目录下即可,但是最好的解决方案是讲将两个so文件存放到项目目录下,然后使用
System.load(System.getProperty(“user.dir”)+/so文件相对路径)。
解决方案:直接使用网卡名称打开网卡
Pcap pcap=Pcap.openLive("eth0",64*1024,Pcap.MODE_NON_PROMISCUOUS,new StringBuilder());
//Pcap pcap=Pcap.openLive(网卡名称,包大小,网卡模式,错误信息);
说明:网卡名称一般为eth0等
包大小一般为64*1024
网卡模式一般为Pcap.MODE_NON_PROMISCUOUS混合模式
错误信息其中存放的是当网卡打开失败后返回的系统信息,一般为StringBuilder
通过上面得到的Pcap网卡对象就可以循环捕包了,大致程序逻辑如下:
由于会一台机器上可能会有多个网卡,所以抓包前应先进行网卡的绑定
Pcap pcap=Pcap.openLive("eth0",64*1024,Pcap.MODE_NON_PROMISCUOUS,new StringBuilder());
PcapBpfProgram filter = new PcapBpfProgram();
String expression=” ”;
int r=pcap.compile(filter , expression , 0, 0);
if(r==Pcap.OK){
Pcap.setFilter(filter);
}
PcapPacketHandler
特别说明:
1. 表达式expression的重要性,因为同一时刻网卡有可能会收到大量的包,如果不加上过滤器那么程序的处理能力肯定是达不到的。
2. 过滤表达式示例:
String expression="ip and udp src port 12345 and dst port 54321 and eth src not 11:22:33:44:55:66";
该表达式过滤使用了IP和UDP协议,并且源端口为12345,目的端口为54321,并且源mac地址不为11:22:33:44:55:66,只有满足上述所有条件,才会被到。
|
内容 |
长度 |
eth头 |
源mac,目的mac |
14字节 |
ip头 |
源IP,目的IP |
20字节 |
udp头 |
源端口,目的端口 |
8字节 |
负载 |
数据 |
不定 |
1. 得到mac
EtherNet ethe=newEtherNet();
PcapPcaket pcaket;
if(pcaket.hasHeader(ethe)){
String srcMac= FormatUtils.mac(ethe.source());
String dstMac= FormatUtils.mac(ethe.destination());
}
2. 得到ip
Ip4 ip =new Ip4();
byte srcIp=new byte[4];
byte dstIp=new byte[4];
PcapPcaket pcaket;
If(pcaket.hasHeader(ip)){
srcIp =ip.source();
dstIp=ip. Destination();
}
3. 得到端口
Udp udp=new Udp();
PcapPcaket pcaket;
If(pcaket.hasHeader(usp)){
int srcPort=udp.source();
int dstPort=udp.destination();
}