我写的一段在JAVA中调用 JPCAP来监听网络UDP包的程序,前面刷新JSP网页都没什么事,但是刷新超过10次就会弹出下面的错误,有人知道怎么解决吗?我用的是JPCAP-0.7版本的。 严重: Servlet.service() for servlet jsp threw exception 
java.io.IOException: Unable to open a device: 10 devices are already opened. 
at jpcap.Jpcap.<init>(Jpcap.java:51) 
。。省略 
JAVA 代码: 
import java.io.IOException; import jpcap.EthernetPacket; 
import jpcap.IPAddress; 
import jpcap.Jpcap; 
import jpcap.JpcapCaptor; 
import jpcap.JpcapHandler; 
import jpcap.NetworkInterface; 
import jpcap.NetworkInterfaceAddress; 
import jpcap.Packet; 
import jpcap.PacketReceiver; 
import jpcap.UDPPacket; 
import java.io.*; 
public class Jpcaphandler implements JpcapHandler { 
public void handlePacket(Packet packet){ int l=0; 
String []str4=new String[1000]; 
if (packet instanceof UDPPacket){ UDPPacket udpPacket = (UDPPacket)packet; 
EthernetPacket ethernetPacket=(EthernetPacket)packet.datalink; 
IPAddress address = udpPacket.dst_ip; 
str4[l]=address.toString(); 
l++; 

} } JSP调用JAVA的代码: 
String[] devices = Jpcap.getDeviceList(); 
String deviceName = devices[1]; 
Jpcap jpcap = Jpcap.openDevice(deviceName, 1024,true, 10000); 
Jpcaphandler hander=new Jpcaphandler(); 
jpcap.loopPacket(100, hander); 
jpcap.close();

解决方案 »

  1.   

    String[] devices = Jpcap.getDeviceList(); 
    String deviceName = devices[1]; 
    Jpcap jpcap = Jpcap.openDevice(deviceName, 1024,true, 10000); 
    Jpcaphandler hander=new Jpcaphandler(); 
    jpcap.loopPacket(100, hander); 
    jpcap.close();------------以上代码每次前台刷新,都会打开一次device,然后调用handler来处理接收到的100个包。
    由于从网络上接收100个包的时间是不确定的,所以我们无法知道loopPacket(100,handler)这个方法什么时候会返回
    (因为只有这个方法返回后,jpcap.close()才会被调用),
    所以,当你刷新前台页面的时候,后台会并发打开很多个Device,最终超出了jpcap内部设置的限制。
    ------------我不明白你是需要同时打开多次Device来侦听包,还是只需要一个线程,
    如果只需要一个线程的话,建议将以上代码封装到一个单例模式的类中,只有第一次调用的页面可以打开device,后续的刷新发现Device还没有关闭,
    则直接返回。
      

  2.   

    我是需要每次只打开一个Device来侦听就可以了。
    如果只需要一个线程的话,建议将以上代码封装到一个单例模式的类中,只有第一次调用的页面可以打开device,后续的刷新发现Device还没有关闭, 
    则直接返回。 这个怎么做~~~~麻烦贴下代码 谢谢了 给分
      

  3.   

    因为你的程序总体结构我不太清楚,我只能写出大致的代码public class MyOpenDevice {
    private static MyOpenDevice instance;

    public static MyOpenDevice getInstance(){
    if (instance==null){
    instance=new MyOpenDevice();
    }
    return instance;
    }
    private Jpcaphandler hander;
    public void openDevice(){
    if (handler!=null){
    System.out.println("已经在处理中了。");
    return;
    }
    String[] devices = Jpcap.getDeviceList(); 
    String deviceName = devices[1]; 
    Jpcap jpcap = Jpcap.openDevice(deviceName, 1024,true, 10000); 
    hander=new Jpcaphandler(); 
    jpcap.loopPacket(100, hander); 
    jpcap.close();
    }}
    在原来打开device的地方,调用:MyOpenDevice.getInstance().openDevice();
    如果已经有线程在侦听,这个方法立即返回,并打印:已经在处理中了。
      

  4.   

    谢谢了
    其实也可以这样 在JSP 页面调用的时候
    先判断handler  是否为空
    如果为空,则不执行调用Device去侦听,而采用原来的数据。
    直到handler释放才调用,