这学期,我们网络的课程设计的软件部分,是编写一个捕获数据包的程序。本来,我打算用C++编写基于WinPcap的程序,不过由于我不会MFC,所以只能做出Dos这样的界面,于是,我就用基于JpCap的Java语言写。
程序写完了,在我自己机器上运行,没什么问题,难得出现一次Unexpected Error的提示,我也没理会它。
今天,去学校的机房运行,顿时傻眼,因为程序根本不能运行,每次运行都会出现Unexpected Error。以下是程序:
import jpcap.*;
import jpcap.packet.*;
import java.sql.Timestamp;
//创建一个执行接口PacketReceiver类的一个实例IP类
class IP implements PacketReceiver
{
public void receivePacket(Packet packet)
{
System.out.println("捕获一个IP数据报");
System.out.println();
System.out.println("捕获时间为:"+new Timestamp((packet.sec * 1000) + (packet.usec / 1000)) );
System.out.println();
System.out.println("IP头长度为:"+packet.header.length);
System.out.println();
System.out.println("目的IP地址为:"+((IPPacket)packet).dst_ip.toString());
System.out.println();
System.out.println("数据内容为:");
for(int i=0;i<packet.data.length;i++){
System.out.print(Byte.toString(packet.data[i]));}
System.out.println();
System.out.println();
}
public static void main(String[] args) throws Exception
{
//返回一个网络设备列表
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//打开连接设备实例1,提取每次数据包中前2000字节,设置网卡为混杂模式,最后指定超时时间为20
JpcapCaptor jpcap = JpcapCaptor.openDevice( devices[1], 2000, true, 20);
//指定捕获一个数据包,如果设为-1,则为无限循环地捕获,调用抽象方法void receive(Packet packet)
jpcap.loopPacket(-1, new IP());
}
}
根据分析,程序在(IPPacket)packet出错,错误提示信息大致为:
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d75c5cc, pid=2320, tid=1692
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_08-b03 mixed mode, sharing)
# Problematic frame:
# V [jvm.dll+0x9c5cc]
#
# An error report file with more information is saved as hs_err_pid2320.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
很明显,出错的原因肯定是我们的packet不能转换成IPPacket,也就是说,我们捕捉到的数据包不是IPPacket。
解决这个问题的最简单的方法,就是把处理packet的程序放到try和catch中,那么,一旦程序在IPPacket处发生奔溃,那就说明程序捕获的不是IP数据报,那就不会再显示出来,当然,在catch块中,你也可以进行其它的操作。
修改
receivePacket函数中的程序如下:
public void receivePacket(Packet packet)
{
try
{
System.out.println("捕获一个IP数据报");
System.out.println();
System.out.println("捕获时间为:"+new Timestamp((packet.sec * 1000) + (packet.usec / 1000)) );
System.out.println();
System.out.println("IP头长度为:"+packet.header.length);
System.out.println();
System.out.println("目的IP地址为:"+((IPPacket)packet).dst_ip.toString());
System.out.println();
System.out.println("数据内容为:");
for(int i=0;i<packet.data.length;i++){
System.out.print(Byte.toString(packet.data[i]));}
System.out.println();
System.out.println();
}
catch( Exception e )
{
}
}
出现这个错误的原因,我觉得是因为学校的机房中了病毒的缘故,那些病毒会发送很多不规则的数据包,从而导致了packet和IPPacket之间的强制转换不成功,从而导致程序奔溃。同时,我们机房中还是用了ARP协议,所以,在网络中,也有ARP的数据包。当我们想将packet强制转换成ARP的包,也是不行的。
所以,当你出现了以上问题,请你检查一下你的程序里面是否存在着包之间的强制类型转换,并且,一定要把强制类型转换的语句放到try...catch语句块中进行处理。
最后,附上我写的程序,供大家学习和下载
特别注意:
1:JCCFrame.java是主程序
2:在运行程序前,请依次安装WinPcap3.0和JpCap0.6。我特别推荐安装JpCap0.6而不是0.7,因为0.6的安装包做的比较好,一次安装,全部到位,如果你用0.7,那么你还要为JpCap.jar进行其它配置,很容易出错。
3:在安装JpCap0.6时,请选中JpCap0.6 for JDK。
下载地址:
http://www.cnitblog.com/Files/CoffeeCat/JCCFrame.rarCoffeeCat
2007年7月13日