Menu

Tutorial 2 Example 2

Bernardo Bulgarelli Labronici

Example 2

Multithread and packet Capture. How to proper break loops from other threads.

        //Create a connection to pcap
        //For now let's ignore maxFrameLength, since it depends on the creation
        //of filter to work.
        Capture cap = new Capture(0);


        try {


            //Let's get all the devices available in the machine for pcap
            //If any error occurs it will be throw as an NetworkDeviceException
            List<NetworkDevice> networkDevices = cap.getNetworkDevices();

            //Assuming the first device is a valid device for capture.
            //we can use it.
            //Print basic info of device
            //We will connect to this device to sniff packets from
            NetworkDevice device = networkDevices.get(0);

            System.out.println();
            System.out.println("  Pcap Device Name: " + device.getName());
            System.out.println("Device Description: " + device.getDescription());

            //Print all address that this device can have
            //a device can have multiple address
            //(e.g. Ipv4 and Ipv6; Multihoming Ipv4; etc...)
            for(DeviceAddress deviceAddress :  device.getAddresses()){

                if(deviceAddress.getAddress() != null){
                    System.out.print("           Address: " + deviceAddress.getAddress().getHostAddress());

                    if(deviceAddress.getMask() != null)
                        System.out.print("/" + deviceAddress.getMask().getHostAddress());

                    if(deviceAddress.getBroadcast() != null)
                        System.out.print(" brdcast: " + deviceAddress.getBroadcast().getHostAddress());
                    System.out.println();
                }
            }


            System.out.println();
            //Add a new adapter to the Capture Listener.
            //Adapters can be of type CaptureAdapter for parsed packets, as the one in this example
            //or can be the type CaptureRawAdapter to receive packets as a ByteBuffer
            cap.addListener(new CaptureAdapter(){

                //Count frames
                private int count = 0; 

                //This function is called by Sniffer4J.Dll for each new received Frame
                @Override
                public void capture(Frame frame) {

                    //counting frames
                    count++;

                    //Capture length is the length actually captured by pcap
                    //Total length is the length of the original frame
                    //if maxFrameLength is used in Capture Class creation
                    //Those values might be different
                    System.out.println("      Frame Number: " + count +
                            " Size captured: " + frame.getCaptureLength() +
                            " Total Size: " + frame.getTotalLength());
                }

            }); 


            //Connect to device (ignore timeout, show packets as they arrive)
            cap.connect(device, -1);


            //Define a Thread that will call CaptureFramesLoo.
            //This thread will loop FOREVER until a external command (BreakLoop)
            //Stops the capture, and the thread can finish
            Thread tn = new Thread(new Runnable(){

                @Override
                public void run() {
                    try {

                        //Start the Capture loop and get frames FOREVER
                        //Any negative number means infinity
                        cap.CaptureFramesLoop(-1);

                    } catch (Exception e) { 
                        //If Main thread do not wait pcap finishes 
                        //CaptureFramesLoop gracefully after BreakLoop
                        //An exception will probably be raised here 
                        //See below
                        e.printStackTrace();
                    }}
            });

            //Start thread
            tn.start();

            //Sleeps the main thead for 5 seconds
            //mean while the defined thread tn above is capturing and printing packets for 
            //us
            Thread.sleep(5000);

            //Break the loop
            //Commands Pcap to break the loop. Have to wait until pcap gracefully ends 
            //CaptureFramesLoop before closes the device or an excepton will be raised
            //You can do so by waiting the thread to finishes, joining the thread
            cap.BreakLoop();


            //Very important to join thread, wait CaptureFramesLoop finishes gracefully
            tn.join();

            System.out.println("Have Breaked Loop and waited for it to finish gracefully");

            //Close the Capture Device
            //If you invert this command with tn.join, probably an exception will be raised
            cap.close();

        }catch(NetworkDeviceException e){

            System.err.println("Error in the cap.getNetworkDevices();");
            e.printStackTrace();

        }catch(CaptureS4JException e){

            System.err.println("Error in the connection.");
            e.printStackTrace();

        }catch (JNIException e) {

            System.err.println("Error With the Dll");
            e.printStackTrace();

        } catch (InterruptedException e) {

            System.err.println("Thread Error. This is not Sniffer4J problem, Ops...");
            e.printStackTrace();

        } catch (NotSupportedDatalinkS4JException e1) {

            System.err.println("Datalink not Supported, only Ethernet");
            e1.printStackTrace();
        }

In this example, the spanned thread capture packets in an infinity loop, while the main thread waits for 5 seconds. When the main thread wake up it send a break command to interrupt any Capture loop (Loop or Dispatch).
The main thread have to wait for the spanned thread to gracefully finishes, or an exception will be raised.
In

            Thread tn = new Thread(new Runnable(){

                @Override
                public void run() {
                    try {

                        //Start the Capture loop and get frames FOREVER
                        //Any negative number means infinity
                        cap.CaptureFramesLoop(-1);

                    } catch (Exception e) { 
                        //If Main thread do not wait pcap finishes 
                        //CaptureFramesLoop gracefully after BreakLoop
                        //An exception will probably be raised here 
                        //See below
                        e.printStackTrace();
                    }}
            });

The spanned thread is created, and start to capture packets for an infinity amount of packets

cap.CaptureFramesLoop(-1);

The negative value means infinity.

Then the main thread waits for 5 seconds, than breaks any running loop.

            Thread.sleep(5000);
            cap.BreakLoop();

Finally the main thread join the spanned thread until it finishes

  tn.join();

Warning this last step is critical.


Related

Wiki: Tutorial

MongoDB Logo MongoDB