Захват пакетов ping вызывает исключение (слишком много экземпляров)

Я написал фрагмент кода для обработки пинга с использованием JPCAP. код, который я написал, приведен ниже:

while (true) {
    try {
    PacketCapture m_pcap;
    m_pcap = new PacketCapture();
    m_pcap.open("\\Device\\NPF_{007262BD-....-7EE83D72EBEA}",true);//param 1 is actual device ID
    m_pcap.setFilter("proto ICMP", true);
    pktlistener a = new pktlistener(); //handles the packet
    m_pcap.addPacketListener(a);
    System.out.println("going to sleep");
    Thread.sleep(1 * 1000);// Waiting for 1 second before ending capture
    System.out.println("woken up");
    m_pcap.removePacketListener(a);
    m_pcap.endCapture();
    m_pcap.close();
    a = null;
    m_pcap = null;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Теперь приведенный выше код запускает новый захват через каждую секунду. Проблема с вышеизложенным заключается в том, что после 10 запусков цикла возникает исключение:

 Exception in thread "Thread-6" java.lang.Error: Too many instances, exceeds 10
    at net.sourceforge.jpcap.capture.PacketCapture.<init>(PacketCapture.java:51)

Q1. Как мне предотвратить это. Мне нужно запускать новый PacketCapture каждую секунду.

Q2. Есть ли другой более простой способ захвата сообщений ping, полученных в системе через java?


person Rishabh    schedule 31.05.2013    source источник
comment
Пройдите по этой ссылке. Это может помочь вам. [1]: stackoverflow.com/questions/4452814/   -  person Chakit Patel    schedule 31.05.2013


Ответы (1)


Вы не можете использовать конструктор PacketCapture более десяти раз. Это поведение жестко закодировано, поскольку конструктор выглядит следующим образом:

/**
 * Create a new packet capture instance.
 */
public PacketCapture() {
    if (nextInstance >= INSTANCE_MAX) {
        throw new Error("Too many instances, exceeds " + INSTANCE_MAX);
    }

    instanceNum = nextInstance++;
}

Чтобы перехватить запросы ping, вы должны попробовать следующий код

public class Main {

    public static void main(String[] args) throws CaptureDeviceLookupException {
        Capture cap = new Capture();
        cap.doCapture();
    }
}

class PingListener implements PacketListener {

    @Override
    public void packetArrived(Packet packet) {
        try {
            // only ICMP packages
            if (packet instanceof ICMPPacket) {
                ICMPPacket tcpPacket = (ICMPPacket) packet;
                int data = tcpPacket.getMessageCode();
                // only echo request packages
                if (data == ICMPMessages.ECHO) {
                    // print source and destination.
                    String srcHost = tcpPacket.getSourceAddress();
                    String dstHost = tcpPacket.getDestinationAddress();
                    System.out.println("Ping from: " + srcHost + " to " + dstHost);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

class Capture {
    public void doCapture() {
        // create capture instance
        PacketCapture capture = new PacketCapture();
        // add listener that handles incomming and outgoing packages
        PingListener pingListener = new PingListener();
        capture.addPacketListener(pingListener);
        // m_pcap.setFilter("filter here or in handler", true);

        try {
            capture.open("\\Device\\NPF_{...}", true); // connect capture to device
            while (true) {
                capture.capture(1); // capture one package
            }
        } catch (Exception e) {
            e.printStackTrace(); // exception during capture or handling of
                                 // packages
        } finally {
            // technically never reached as the loop goes on forever.
            // if loop terminates after a while then:

            // remove listener
            capture.removePacketListener(pingListener);
            // end capture (only necessary, if PacketCapture still waits for
            // other packages)
            capture.endCapture();
            // close connection to capture device
            capture.close();
        }
    }
}

Я думаю, что есть недопонимание класса PacketCapture. На самом деле он не захватывает один пакет, а затем отбрасывается. Он открывает соединение с устройством, с которого вы хотите захватить пакеты, а затем начинает прослушивание до тех пор, пока вы удерживаете это соединение. Затем вы начинаете захват n пакетов, вызывая capture.capture(n). Для каждого пакета, поступающего в то время, как «захват» блокирует вашу программу, вызывается слушатель.

В качестве альтернативы вы можете отказаться от цикла while и использовать capture.capture(-1). Это навсегда заблокирует вашу программу, пока вы не закроете захват с другого устройства.

person DKM    schedule 31.05.2013
comment
я на самом деле отправляю HTTP-запросы на сервер. Когда сервер получает запрос, он может или не может пропинговать мою машину. Поэтому мне нужно отслеживать, какой запрос привел к пингу. Для реализации этого я создал фактический PktListener (моего кода) с конструктором, имеющим HTTP-запрос в качестве параметра. И в методе packetArrived, если приходит пинг, я печатаю HTTP-запрос (из переменной, локальной для этого класса) в файл, таким образом определяя, какой запрос сгенерировал пинг. Следовательно, мне нужно запускать новый экземпляр каждую секунду. - person Rishabh; 31.05.2013
comment
@Rishabh отредактировал ответ, чтобы он соответствовал вашей проблеме. Я думаю, что существует недопонимание того, что делает PacketCapture. - person DKM; 31.05.2013
comment
Код работает нормально. Это точно решит мою проблему. Спасибо! - person Rishabh; 31.05.2013