基於java的網絡抓包技術研究與實現(轉)

 

一、實驗內容描述

本實驗是用java實現的網絡抓包程序,在windows環境下安裝winpcap4.0jpcap6.0後,下載eclipsejigloo插件(一種在eclipse底下作圖形化開發的工具),將其安裝好,然後就可以進行java的網絡抓包圖形化開發了。

二、原理與關鍵技術

2.1 網絡抓包技術原理

網絡層上有各種各樣的數據包,它們以不同的幀格式在網絡層上進行傳輸,但是在傳輸時它們都遵循相同的格式,即有相同的長度,如果一種協議的幀格式達不到這種長度,就讓其補齊,以達到我們的要求。

2.2 網絡抓包關鍵技術

無論是在windows操作系統下還是在linux操作系統下,要想捕獲網絡上的數據包,必須要對網卡進行控制,因爲本機的數據報從網絡上來到本機是通過網卡然後再保存到本地緩衝區上的,所以要抓獲網包就必須調用網卡驅動中的對外函數,在linux系統中有net.h文件,可以調用net.h文件中的函數來操作網卡,可以直接編程實現,但爲了更方便的使用,可以安裝一個叫libpcap的軟件,這樣調用函數更好用,而在windows系統中,因爲源代碼不對外公開,所以要安裝一個叫winpcap的軟件,這樣用CVC++就可以實現了,但因爲我用的是java語言來實現的,所以無論是在哪個系統都要安裝一個叫jpcap的軟件,它本身就把底層的函數又封裝了一下,這樣就可以讓java來使用了。

三、設計與實現

3.1 基於java的設計方案

我的這個網絡抓包程序是圖形化操作界面,在菜單欄點擊抓包按鈕後選擇網卡和過濾字還有最長字長,點擊開始,然後就可以開始抓包了,在主界面中就會顯示出一行又一行的數據,這些數據就是抓獲到的數據包。

3.2 具體實現

1、安裝winpcap4.0jpcap6.0

2、下載eclipse3.3jigloojiglooeclipse底下的插件,是用來支持eclipse底下的java 圖形化開發的。

3、編寫java抓包程序:

建立三個文件,一個主程序,一個抓包程序,一個抓包選項程序對話框程序

第一個程序:主程序如下

package netcap;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

 

import javax.swing.JSeparator;

import javax.swing.JMenuItem;

import javax.swing.JMenu;

import javax.swing.JMenuBar;

 

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.table.*;

import netcap.*;

import jpcap.*;

import jpcap.packet.*;

import java.util.*;

import java.sql.Timestamp;

 

/**

* This code was edited or generated using CloudGarden's Jigloo

* SWT/Swing GUI Builder, which is free for non-commercial

* use. If Jigloo is being used commercially (ie, by a corporation,

* company or business for any purpose whatever) then you

* should purchase a license for each developer using Jigloo.

* Please visit www.cloudgarden.com for details.

* Use of Jigloo implies acceptance of these licensing terms.

* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR

* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED

* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.

*/

public class JFrameMain extends javax.swing.JFrame implements ActionListener{

 

       private JMenuItem exitMenuItem;

       private JSeparator jSeparator2;

       private JMenuItem saveAsMenuItem;

       private JMenuItem saveMenuItem;

       private JMenuItem stopMenuItem;

       private JMenuItem startMenuItem;

       private JMenu Menu;

       private JMenuBar jMenuBar1;

      

       JTable tabledisplay = null;

       Vector rows,columns;

       DefaultTableModel tabModel;

       JScrollPane scrollPane;

       JLabel statusLabel;

      

       Netcaptor captor = new Netcaptor();

 

       /**

       * Auto-generated main method to display this JFrame

       */

       public static void main(String[] args) {

              JFrameMain inst = new JFrameMain();

              inst.setVisible(true);

       }

      

       public JFrameMain() {

              super();

              initGUI();

       }

      

       private void initGUI() {

              try {

                     setSize(400, 300);

                     {

                            jMenuBar1 = new JMenuBar();

                            setJMenuBar(jMenuBar1);

                            {

                                   Menu = new JMenu();

                                   jMenuBar1.add(Menu);

                                   Menu.setText("/u6293/u5305");

                                   Menu.setPreferredSize(new java.awt.Dimension(35, 21));

                                   {

                                          startMenuItem = new JMenuItem();

                                          Menu.add(startMenuItem);

                                          startMenuItem.setText("開始");

                                          startMenuItem.setActionCommand("start");

                                          startMenuItem.addActionListener(this);

                                   }

                                   {

                                          stopMenuItem = new JMenuItem();

                                          Menu.add(stopMenuItem);

                                          stopMenuItem.setText("停止");

                                          stopMenuItem.setActionCommand("stop");

                                          stopMenuItem.addActionListener(this);

                                   }

                                   {

                                          saveMenuItem = new JMenuItem();

                                          Menu.add(saveMenuItem);

                                          saveMenuItem.setText("保存");

                                   }

                                   {

                                          saveAsMenuItem = new JMenuItem();

                                          Menu.add(saveAsMenuItem);

                                          saveAsMenuItem.setText("保存爲 ...");

                                   }

                                   {

                                          jSeparator2 = new JSeparator();

                                          Menu.add(jSeparator2);

                                   }

                                   {

                                          exitMenuItem = new JMenuItem();

                                          Menu.add(exitMenuItem);

                                          exitMenuItem.setText("Exit");

                                          exitMenuItem.setActionCommand("exit");

                                          exitMenuItem.addActionListener(this);

                                   }

                            }

                     }

                    

                     rows=new Vector();

                     columns= new Vector();

                    

                     columns.addElement("數據報時間");

                     columns.addElement("IP地址");

                     columns.addElement("目的IP地址");

                     columns.addElement("首部長度");

                     columns.addElement("數據長度");

                     columns.addElement("是否分段");

                     columns.addElement("分段偏移量");

                     columns.addElement("首部內容");

                     columns.addElement("數據內容");

 

                    

                     tabModel=new DefaultTableModel();

                     tabModel.setDataVector(rows,columns);

                     tabledisplay = new JTable( tabModel );

                     scrollPane= new JScrollPane(tabledisplay);

                     this.getContentPane().add( new JScrollPane(tabledisplay),BorderLayout.CENTER);

                    

                     statusLabel=new JLabel("06610班張琛雨 066100583");

                     this.getContentPane().add(statusLabel,BorderLayout.SOUTH);

              } catch (Exception e) {

                     e.printStackTrace();

              }

       }

      

       public void actionPerformed(ActionEvent event){

              String cmd=event.getActionCommand();

             

              if(cmd.equals("start")){

                     captor.capturePacketsFromDevice();

                     captor.setJFrame(this);

              }

              else if(cmd.equals("stop")){

                     captor.stopCapture();

              }

              else if(cmd.equals("exit")){

                     System.exit(0);

              }

       }

 

       public void dealPacket( Packet packet )

       {

              try

              {

                     Vector r=new Vector();

                     String strtmp;

                     Timestamp timestamp = new Timestamp((packet.sec * 1000) + (packet.usec / 1000));

                    

                     r.addElement( timestamp.toString() );  //數據報時間

                     r.addElement(((IPPacket)packet).src_ip.toString());    //IP地址

                     r.addElement(((IPPacket)packet).dst_ip.toString());    //目的IP地址

                     r.addElement( packet.header.length );   //首部長度

                     r.addElement( packet.data.length );             //數據長度

                     r.addElement( ((IPPacket)packet).dont_frag == true ? "分段" : "不分段" );                          //是否不分段

                     r.addElement( ((IPPacket)packet).offset );          //數據長度

      

                     strtmp = "";

                     for(int i=0;i<packet.header.length;i++){            

                            strtmp += Byte.toString(packet.header[i]);

                     }

                     r.addElement(strtmp);    //首部內容

      

                     strtmp = "";

                     for(int i=0;i<packet.data.length;i++){         

                            strtmp += Byte.toString(packet.data[i]);

                     }

                     r.addElement(strtmp);    //數據內容

                                                       

                     rows.addElement(r);

                     tabledisplay.addNotify();

              }

              catch( Exception e)

              {

                    

              }

       }

}

在這裏定義了一個向量r,當有數據包產生時,便將數據包賦值給rrows.AddElementr)語句便將r添加到向量rows中,然後tabledisplay.addNotify();語句就會刷新界面將新的數據包顯示出來。

 

第二個程序:抓包

package netcap;

 

import java.io.File;

import java.util.Vector;

 

import javax.swing.JFileChooser;

import javax.swing.JOptionPane;

 

import jpcap.JpcapCaptor;

import jpcap.PacketReceiver;

import jpcap.JpcapWriter;

import jpcap.packet.Packet;

 

public class Netcaptor {

 

       JpcapCaptor jpcap = null;

       JFrameMain frame;

      

       public void setJFrame(JFrameMain frame){

              this.frame=frame;

       }

      

       public void capturePacketsFromDevice() {

 

              if(jpcap!=null)

                     jpcap.close();

                    

              jpcap = Jcapturedialog.getJpcap(frame);

             

              if (jpcap != null) {

                     startCaptureThread();

              }

 

       }

      

       private Thread captureThread;

      

       private void startCaptureThread(){

             

              if(captureThread != null)

                     return;

              captureThread = new Thread(new Runnable(){

                     public void run(){

                            while(captureThread != null){

                                   jpcap.processPacket(1, handler);

                            }

                     }

              });

              captureThread.setPriority(Thread.MIN_PRIORITY);

              captureThread.start();

       }

      

       void stopcaptureThread(){

              captureThread = null;

       }

      

       public void stopCapture(){

              System.out.println(2);

              stopcaptureThread();

       }

      

       private PacketReceiver handler=new PacketReceiver(){

              public void receivePacket(Packet packet) {

                     //System.out.println(packet);

                     frame.dealPacket(packet);

              }

             

       };

}

定義一個抓包對象JpcapCaptor jpcap = null;但點擊開始時調用private void startCaptureThread()方法開始抓包,jpcap.processPacket(1, handler);語句能夠反覆調用handler所指向的方法,這個方法中定義的packet就是網絡上抓到的數據包,經過frame.dealPacket(packet);就可以顯示在主界面上。

程序三:抓包選項

package netcap;

 

import javax.swing.JFrame;

import jpcap.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

 

 

/**

* This code was edited or generated using CloudGarden's Jigloo

* SWT/Swing GUI Builder, which is free for non-commercial

* use. If Jigloo is being used commercially (ie, by a corporation,

* company or business for any purpose whatever) then you

* should purchase a license for each developer using Jigloo.

* Please visit www.cloudgarden.com for details.

* Use of Jigloo implies acceptance of these licensing terms.

* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR

* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED

* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.

*/

public class Jcapturedialog extends javax.swing.JDialog implements ActionListener {

 

       /**

       * Auto-generated main method to display this JDialog

       */

       static JpcapCaptor jpcap=null;

       private JRadioButton wholeRadioButton;

       private JPanel buttonPanel;

       private JButton cancelButton;

       private JButton okButton;

       private JRadioButton userRadioButton;

       private JRadioButton headRadioButton;

       private JPanel netPanel;

       private JTextField caplenTextField;

       private JPanel caplenPanel;

       private JTextField TextField;

       private JPanel filterPanel;

       private JCheckBox CheckBox;

       private JComboBox netJComboBox;

       private JPanel jPanel_east;

       private JPanel jPanel_west;

 

       NetworkInterface[] devices;

      

       public static void main(String[] args) {

              JFrame frame = new JFrame();

              Jcapturedialog inst = new Jcapturedialog(frame);

              inst.setVisible(true);

       }

      

       public Jcapturedialog(JFrame frame) {

              super(frame,"選擇要檢測的網卡並設置參數",true);

 

              try {

                     BoxLayout thisLayout = new BoxLayout(

                            getContentPane(),

                            javax.swing.BoxLayout.X_AXIS);

                     getContentPane().setLayout(thisLayout);

                     {

                            jPanel_west = new JPanel();

                            jPanel_west.setLayout(new BoxLayout(jPanel_west,BoxLayout.Y_AXIS));

                            getContentPane().add(jPanel_west);

                            {

                                   netPanel = new JPanel();

                                   FlowLayout netPanelLayout = new FlowLayout();

                                   netPanelLayout.setAlignOnBaseline(true);

                                   netPanel.setBorder(BorderFactory.createTitledBorder("選擇網卡"));

                                   netPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

                                   jPanel_west.add(netPanel);

                                   netPanel.setLayout(netPanelLayout);

//                                 netPanel.setPreferredSize(new java.awt.Dimension(239, 56));

                                   {

                                          devices = JpcapCaptor.getDeviceList();

                                          if(devices == null){

                                                 JOptionPane.showMessageDialog(frame, "沒有找到網卡");

                                                 dispose();

                                                 return;

                                          }

                                          else{

                                                 String[] names = new String[devices.length];

                                                 for(int i=0;i < names.length;i++){

                                                        names[i] = (devices[i].description == null?devices[i].name:devices[i].description);

                                                 }

                                                 netJComboBox = new JComboBox(names);

                                          }

                                                 netPanel.add(netJComboBox);     

                                   }

                            }

                            {

                                   CheckBox = new JCheckBox();

                                   jPanel_west.add(CheckBox);

                                   FlowLayout CheckBoxLayout = new FlowLayout();

                                   CheckBoxLayout.setAlignOnBaseline(true);

                                   CheckBox.setText("/u662f/u5426/u8bbe/u7f6e/u4e3a/u6df7/u6742/u6a21/u5f0f");

                                   CheckBox.setLayout(null);

                            }

                            {

                                   filterPanel = new JPanel();

                                   filterPanel.setBorder(BorderFactory.createTitledBorder("捕獲過濾器"));

                                   filterPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

                                   FlowLayout filterPanelLayout = new FlowLayout();

                                   filterPanelLayout.setAlignment(FlowLayout.LEFT);

                                   filterPanelLayout.setAlignOnBaseline(true);

                                   jPanel_west.add(filterPanel);

                                   filterPanel.setLayout(filterPanelLayout);

                                   {

                                          TextField = new JTextField(20);

                                          filterPanel.add(TextField);

                                   }

                            }

                     }

                     {

                            jPanel_east = new JPanel();

                            jPanel_east.setLayout(new BoxLayout(jPanel_east,BoxLayout.Y_AXIS));

                            getContentPane().add(jPanel_east);

 

                            {

                                   caplenPanel = new JPanel();

                                   caplenPanel.setBorder(BorderFactory.createTitledBorder("最長字長"));

                                   caplenPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

                                   jPanel_east.add(caplenPanel);

                                   caplenPanel.setLayout(new BoxLayout(caplenPanel,BoxLayout.Y_AXIS));

 

                                   {

                                          caplenTextField = new JTextField(20);

                                          caplenPanel.add(caplenTextField);

                                          caplenTextField.setText("1514");

                                          caplenTextField.setEnabled(false);

                                   }

                                   {

                                          wholeRadioButton = new JRadioButton();

                                          FlowLayout userRadioButtonLayout = new FlowLayout();

                                          userRadioButtonLayout.setAlignOnBaseline(true);

                                          caplenPanel.add(wholeRadioButton);

                                          wholeRadioButton.setText("/u6574/u4e2a/u6570/u636e/u62a5");

                                          wholeRadioButton.setSelected(true);

 

                                          wholeRadioButton.addActionListener(this);

                                   }

                                   {

                                          headRadioButton = new JRadioButton();

                                          caplenPanel.add(headRadioButton);

                                          headRadioButton.setText("/u4ec5/u9996/u90e8");

 

                                          headRadioButton.addActionListener(this);

                                   }

                                   {

                                          userRadioButton = new JRadioButton();

                                          caplenPanel.add(userRadioButton);

                                          userRadioButton.setText("/u5176/u4ed6/u90e8/u5206");

 

                                          userRadioButton.addActionListener(this);

                                   }

                                   ButtonGroup group=new ButtonGroup();

                                   group.add(wholeRadioButton);

                                   wholeRadioButton.setActionCommand("Whole");

                                   group.add(headRadioButton);

                                   headRadioButton.setActionCommand("Head");

                                   group.add(userRadioButton);

                                   userRadioButton.setActionCommand("user");

                            }

                            {

                                   buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));

//                                 buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));

                                   jPanel_east.add(buttonPanel);

 

                                   {

                                          okButton = new JButton();

                                          buttonPanel.add(okButton);

                                          FlowLayout cancelButtonLayout = new FlowLayout();

                                          cancelButtonLayout.setAlignOnBaseline(true);

                                          okButton.setText("/u786e/u5b9a");

 

                                          okButton.setActionCommand("ok");

                                          okButton.addActionListener(this);

                                   }

                                   {

                                          cancelButton = new JButton();

                                          buttonPanel.add(cancelButton);

                                          cancelButton.setText("/u53d6/u6d88");

 

                                          cancelButton.setActionCommand("cancel");

                                          cancelButton.addActionListener(this);

                                   }

//                                 buttonPanel.setAlignmentX(Component.RIGHT_ALIGNMENT);

                            }

                     }

                     getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.X_AXIS));

 

                     getContentPane().add(jPanel_west);

 

                     getContentPane().add(jPanel_east);

 

                     pack();

 

              } catch (Exception e) {

                     e.printStackTrace();

              }

       }

       public void actionPerformed(ActionEvent evt){

              String cmd=evt.getActionCommand();

             

              if(cmd.equals("Whole")){

                     caplenTextField.setText("1514");

                     caplenTextField.setEnabled(false);

              }else if(cmd.equals("Head")){

                     caplenTextField.setText("68");

                     caplenTextField.setEnabled(false);

              }else if(cmd.equals("user")){

                     caplenTextField.setText("");

                     caplenTextField.setEnabled(true);

                     caplenTextField.requestFocus();

              }else if(cmd.equals("ok")){

                     try{

                            int caplen=Integer.parseInt(caplenTextField.getText());

                            if(caplen<68 || caplen>1514){

                                   JOptionPane.showMessageDialog(null,"捕獲長度必須介於 68 1514之間");

                                   return;

                            }

                           

                            jpcap=JpcapCaptor.openDevice(devices[netJComboBox.getSelectedIndex()],caplen,

                                          CheckBox.isSelected(),50);

                           

                            if(TextField.getText()!=null && TextField.getText().length()>0){

                                   jpcap.setFilter(TextField.getText(),true);

                            }

                     }catch(NumberFormatException e){

                            JOptionPane.showMessageDialog(null,"捕獲長度必須是正整數");

                     }catch(java.io.IOException e){

                            JOptionPane.showMessageDialog(null,e.toString());

                            jpcap=null;

                     }finally{

                            dispose();

                     }

             

              }else if(cmd.equals("cancel")){

                     dispose();

              }

       }

      

       public static JpcapCaptor getJpcap(JFrame parent){

              new Jcapturedialog(parent).setVisible(true);

              return jpcap;

       }

}

這一部分主要是界面操作,根據jigloo插件對不同的按鈕和文本框還有其他的組件設置監聽操作,以激發不同的函數操作,主要是devices = JpcapCaptor.getDeviceList();語句和

jpcap=JpcapCaptor.openDevice(devices[netJComboBox.getSelectedIndex()],caplen,

CheckBox.isSelected(),50);語句要選擇一下監聽的網卡,比如說筆記本就有兩個網卡,一個無線一個有線,選擇一下就會監聽相應的網卡。函數

public static JpcapCaptor getJpcap(JFrame parent){

       new Jcapturedialog(parent).setVisible(true);

       return jpcap;

    }

返回jpcap,這個jpcap就是對應的選擇上的網卡對象,接下來就從對應的網卡對象jpcap上不斷得到數據包。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章