1、中南大学课程设计报告课程:计算机网络课程设计题目:基于 Winpcap 的网络流量统计分析指导教师:张伟目录第 1 章 总体设计 1、实体类设计 -P32、功能类设计 -P33、界面设计 -P3第 2 章 详细设计 1、实体类实现 -P42、功能类实现 -P43、界面实现 -P5第 3 章 源代码清单及说明 一、CaptureUtil.java -P7二、MyPcapPacketHandler.java -P9三、PacketMatch.java -P9四、Windows.java -P13第 4 章 运行结果 -P19第五章 心得体会 -P21第 1 章 总体设计1、实体类设计TCP、UPD
2、、ICMP、ARP、广播数据包五个包的数据结构设计2、功能类设计(1)网卡获取(2)包的抓捕(3)包的处理3、界面设计(1)布局(2)按钮功能连接第 2 章 第二章 详细设计一、实体类实现TCP、UPD、ICMP、ARP、广播数据包五个包的数据结构设计。本程序采用 Java 编写,基于 win10pcap。Win10pcap 是 winpcap 在 win10 系统上的适用版本。Java 对于 winpcap 使用 jnetpcap 进行支持。对于 TCP、UPD、ICMP、ARP、广播数据包五种类型的包,在 jnetpcap 的 jar 包中大部分已经封装好了相关的实体类型。对应如下:ARP
3、 实体类:work.Arp;UPD 实体类:work.Icmp;IP 实体类:work.Ip4;TCP 实体类:org.jnetpcap.protocol.tcpip.Tcp;UDP 实体类:org.jnetpcap.protocol.tcpip.Udp;而对于其中的广播数据包,其判断我利用捕获到的 IP 包的目的地址进行判断,若其目的地址为 255.255.255.255,则认为其为广播数据包。2、功能类实现(1)网卡获取电脑上的包的发送与接受都得通过网卡来进行,所以为了完成局域网数据包的捕获和统计,我首先要做的是获取到电脑上的网卡列表,然后选择一个网卡进行包的捕获。而相关代码在 jnetp
4、cap 的官网的示例代码 1 中可以找到,从中可以学习到的是 jnetpcap 的各种使用方法。在我电脑上可以捕获到三个网卡,一个是本机自身的物理网卡,另外两个是虚拟机模拟出的虚拟网卡。(2)包的抓捕Jnetpcap 中包的抓捕也是有着固定的格式的,这在官网的示例代码中也是可以找到的,只要设置好相关的参数,就可以进行抓捕具体方法如下,利用 Pcap 对象的 loop 方法。就是实例化一个 Pcap 对象,然后调用其loop 方法。第一个参数 arg0 代表循环次数,第二个参数就是传入一个 PcapPaketHandler或其子类的对象,这个对象类型是要由我们自己编写的对包处理的方法。(3)包的
5、处理在这里对捕获的包的处理我是编写了一个 PcapPacketHandler 的子类,然后重写了nextPacket()方法。在这个方法里我把捕获到的包当作参数传递个具体的处理方法packetMatch.handlePacket(packet)。packetMatch.handlePacket(packet)方法是由我自己编写的。 handlePacket 是packetMatch 的一个静态方法,可以直接调用。在这个方法里面,它会把捕获到的包的包头和 TCP、 UPD、 ICMP、ARP 、广播数据包五种类型的包的包头进行一一比较,以确认是否抓到了了相对应的包。这儿还用到的就是 jnetpc
6、ap 的内部的一个方法,就是 packet.hasHeader(arg0),通过在arg0 传入已在 jnetpcap 里封装好的包的类型的实例,可以很好的判断该包是属于什么包类型的,是 TCP、 UPD、ICMP、ARP 还是广播数据包。然后内部对于各种包的信息的输出也有很好的支持,可以直接使用相应的 toString 方法,就可以输出各种相关信息。(4 ) 网络流量统计对于各个捕获到的包,分别针对各种类型的包设计了一个 Double 变量用于统计其传送过来相应包头的大小,并在停止抓包后将统计的数据输出在最下方的 TextArea 里面。3、界面实现本程序在设计 GUI 时使用了 Java
7、的一个很好的插件 WindowBuilder。(1)布局一开始使用 Border Layout 布局,安排好各个按钮位置,文本框位置。后来采用Absolute layout,并将窗口大小固定化。在布局的最上方是一个 JToolBar 的实例对象,其中放置有选择网卡、开始抓包、停止抓包、清空记录等四个选项,中间是两个带滚动条的多行文本框,左边的用于显示捕获的包的列表,右边用于显示左边的我们选中的包的具体信息。最下方会在停止抓包按钮生效后输出总的抓包情况。(2)按钮功能连接在布局的最上方是一个 JToolBar 的实例对象,其中放置有选择网卡、开始抓包、停止抓包、清空记录等四个选项,其中选择网卡的
8、功能具体由 JComboBox(多文本选择框)上的选项决定,这个多文本选择框监听着 网卡获取的方法,它会从该方法获得一个网卡列表,然后将其文本输出。开始抓包的方法所对应的事件是抓包的事件,并且该抓包事件是个并发的进程。因为如果不将其设置为并发进程,其会使其它事件一直阻塞,甚至连停止抓包都做不到。停止抓包的事件其实是改变了开始抓包中的一个标志位,让其为假。该标志为为真,抓包程序会一直进行,该标志为为假,抓包停止。下方两个文本框,左边的文本框监听的是开始抓包这个事件,当这个事件开始,这个事件会向文本框传输捕获到的包的列表,然后让其显示。而右边的文本框监听的是左边文本框我们选中的内容的相应事件。因为
9、对于我们捕获到的包我进行了编号,当我们在左边的文本框选中了一个包之后,左边的文本框对应的包的序号会被右边的文本框获取,用于在一个列表中根据序号查找到相对应的包的详细内容,然后将其输出。统计功能的实现是在每个包的具体处理时,在处理包的方法类中已经有定义好几个静态变量用于计数,每个包具体处理时,将相对应的包类型数量加一即可。还定义了其它的变量用于统计流量大小,也是在每个包具体处理时,将相对应的包的大小加到相对应的静态变量上即可。第 3 章 源代码清单及说明CaptureUtil.java/该类负责网卡列表的获取、包的捕获、抓包程序的停止package util;import java.util.A
10、rrayList;import javax.swing.JOptionPane;import org.jnetpcap.Pcap;import org.jnetpcap.PcapIf;import entity.Windows;public class CaptureUtil extends Threadprivate static boolean flag=true;public static int number=2;private static StringBuilder errbuf = new StringBuilder(); / 用于存储任何错误信息/此方法用于获取设备上的网卡设施
11、public static ArrayList CaptureNet()CaptureUtil.flag=false;/下面有部分代码来自 jnetpcap 官网的实例ArrayList alldevs = new ArrayList(); / 用于存储搜索到的网卡/取得设备列表int r = Pcap.findAllDevs(alldevs, errbuf);if (r = Pcap.NOT_OK | alldevs.isEmpty() JOptionPane.showMessageDialog(null,errbuf.toString(),“错误“,JOptionPane.ERROR_ME
12、SSAGE); return null;return alldevs;/此方法用于选取网卡并捕获包public static void CapturePacket(ArrayList alldevs)CaptureUtil.flag=true;PcapIf device = alldevs.get(number);/*System.out.printf(“nChoosing %s on your behalf:n“, device.getDescription();*/打开选中的设备int snaplen = Pcap.DEFAULT_SNAPLEN;/ 默认长度为 65535int flag
13、s = Pcap.MODE_PROMISCUOUS; / 混杂模式,扑获所有类型的包int timeout = 10 * 1000; / 10 seconds in millisPcap pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);if (pcap = null) JOptionPane.showMessageDialog(null,errbuf.toString(),“错误“,JOptionPane.ERROR_MESSAGE);return;PacketMatch packetMatch =
14、 PacketMatch.getInstance(); MyPcapPacketHandler myhandler = new MyPcapPacketHandler(); while(CaptureUtil.flag)pcap.loop(1, myhandler, “/njnetpcap“); pcap.close(); public void run()CaptureUtil.CapturePacket(CaptureUtil.CaptureNet();public static void StopCapturePacket()CaptureUtil.flag=false;public s
15、tatic void ClearPacket()PacketMatch.numberOfPacket=0;PacketMatch.hm.clear();Windows.lItems.clear();PacketMatch.numberOfArp=0;PacketMatch.numberOfTcp=0;PacketMatch.numberOfUdp=0;PacketMatch.numberOfIcmp=0;PacketMatch.numberOfWideSpread=0;MyPcapPacketHandler.java/该类是 PcapPacketHandler 的子类,重写了nextPacke
16、t 方法package util;import org.jnetpcap.packet.PcapPacket;import org.jnetpcap.packet.PcapPacketHandler;public class MyPcapPacketHandler implements PcapPacketHandler Overridepublic void nextPacket(PcapPacket packet, Object arg1) PacketMatch packetMatch = PacketMatch.getInstance(); packetMatch.handlePack
17、et(packet); PacketMatch.java/该类是包处理package util;import java.util.HashMap;import org.jnetpcap.packet.PcapPacket;import work.Arp;import work.Icmp;import work.Ip4;import org.jnetpcap.protocol.tcpip.Tcp;import org.jnetpcap.protocol.tcpip.Udp;import entity.Windows;public class PacketMatch public static H
18、ashMap hm=new HashMap();public static int numberOfPacket=0;private static PacketMatch pm; private Icmp icmp = new Icmp(); private Tcp tcp = new Tcp(); private Udp udp = new Udp(); private Arp arp= new Arp();private Ip4 ip4=new Ip4();public static double totalOfIcmp=0;public static double totalOfTcp=
19、0;public static double totalOfUdp=0;public static double totalOfArp=0;public static double totalOfSpread=0;public static double totalOfIp=0;public static int numberOfWideSpread=0;public static int numberOfUdp=0;public static int numberOfTcp=0;public static int numberOfIcmp=0;public static int number
20、OfArp=0;public static PacketMatch getInstance() if (pm = null) pm = new PacketMatch(); return pm; public void handlePacket(PcapPacket packet) /以下四个包都已可以正确捕获PacketMatch.totalOfIp+=packet.getTotalSize()/(1024.0*1024.0);if (packet.hasHeader(icmp) handleIcmp(packet); if (packet.hasHeader(arp) handleArp(
21、packet); if (packet.hasHeader(tcp) handleTcp(packet); if (packet.hasHeader(udp) handleUdp(packet); /广播数据包的捕获if (packet.hasHeader(ip4) handleIp4(packet);/*以下为实验 IP 地址的获取packet.getHeader(ip4);System.out.println(ip4.toString();byte destinations=new byte4;ip4.destinationToByteArray(destinations);byte so
22、urces=new byte4;ip4.sourceToByteArray(sources);System.out.println(“ip4 destination:“+destinations);System.out.println(“ip4 resource:“+sources);System.out.println(“ip4 destination:“+ip4.destinationToInt();System.out.println(“ip4 resource:“+ip4.sourceToInt();System.out.println(“ip4 destination:“+Packe
23、tMatch.intToIp(ip4.destinationToInt();System.out.println(“ip4 resource:“+PacketMatch.intToIp(ip4.sourceToInt();*/private void handleIp4(PcapPacket packet) packet.getHeader(ip4);if(PacketMatch.intToIp(ip4.destinationToInt().equals(“255.255.255.255“)/这是一个广播数据包System.out.println(“收到一个广播数据包 “);Windows.l
24、Items.add(numberOfPacket, “广播数据包“);hm.put(numberOfPacket, “这是一个广播数据包!“);numberOfWideSpread+;totalOfSpread+=ip4.getLength()/1024.0;numberOfPacket+;private void handleUdp(PcapPacket packet) packet.getHeader(udp); System.out.println(“udp 来源端口“+udp.toString();hm.put(numberOfPacket, udp.toString();Window
25、s.lItems.add(numberOfPacket, “udp“);numberOfUdp+;totalOfUdp+=udp.getLength()/1024.0;numberOfPacket+;private void handleTcp(PcapPacket packet) packet.getHeader(tcp); System.out.println(tcp.toString();hm.put(numberOfPacket, tcp.toString();Windows.lItems.add(numberOfPacket, “tcp“);numberOfTcp+;totalOfT
26、cp+=tcp.getLength()/1024.0;numberOfPacket+;private void handleIcmp(PcapPacket packet) packet.getHeader(icmp); System.out.println(“icmp:“+icmp.toString();hm.put(numberOfPacket, icmp.toString();Windows.lItems.add(numberOfPacket, “icmp“);numberOfIcmp+;totalOfIcmp+=icmp.getLength()/1024.0;numberOfPacket
27、+;private void handleArp(PcapPacket packet) packet.getHeader(arp);System.out.println(“arp:“+arp.toString();hm.put(numberOfPacket, arp.toString();Windows.lItems.add(numberOfPacket, “arp“);numberOfArp+;totalOfArp+=arp.getLength()/1024.0;numberOfPacket+; /以下函数将 Int 类型转化为 Ip 地址public static String intTo
28、Ip(int ipInt)return new StringBuilder().append(ipInt24)Windows.java/该类是 GUI 界面设计package entity;import java.awt.Color;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ItemEvent;import java.awt.event.ItemListener;import java.util.A
29、rrayList;import javax.swing.AbstractAction;import javax.swing.Action;import javax.swing.BorderFactory;import javax.swing.DefaultListModel;import javax.swing.JButton;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JList;import javax.swing.JPanel;import javax.swing.JScrollPan
30、e;import javax.swing.JTextArea;import javax.swing.JToolBar;import javax.swing.border.Border;import javax.swing.border.EmptyBorder;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;import org.jnetpcap.PcapIf;import util.CaptureUtil;import util.PacketMatch;publ
31、ic class Windows extends JFrame private JPanel contentPane;private final Action action = new SwingAction();private final Action action_1 = new SwingAction_1();private final Action action_2 = new SwingAction_2();public static DefaultListModel lItems=new DefaultListModel();private JList list = new JLi
32、st(lItems);private final Action action_3 = new SwingAction_3();private JScrollPane jsp1=new JScrollPane(list);private JTextArea textArea = new JTextArea();private JScrollPane jsp2=new JScrollPane(textArea);private JTextArea textArea_1 = new JTextArea();/* Launch the application.*/public static void
33、main(String args) EventQueue.invokeLater(new Runnable() public void run() try Windows frame = new Windows();frame.setVisible(true); catch (Exception e) e.printStackTrace(););/* Create the frame.*/public Windows() setTitle(“u6293u5305“);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100, 10
34、0, 692, 477);contentPane = new JPanel();contentPane.setBorder(new EmptyBorder(5, 5, 5, 5);setContentPane(contentPane);contentPane.setLayout(null);this.setResizable(false);JToolBar toolBar = new JToolBar();toolBar.setBounds(5, 5, 666, 23);contentPane.add(toolBar);JButton button = new JButton(“u9009u6
35、2E9u7F51u5361“);toolBar.add(button);final JComboBox comboBox = new JComboBox();comboBox.addActionListener(new ActionListener() public void actionPerformed(ActionEvent e) String net=(String)comboBox.getSelectedItem();ArrayList alldevs=CaptureUtil.CaptureNet();int i=0;System.out.println(net);for (Pcap
36、If device : alldevs) if(net.equals(device.getDescription()CaptureUtil.number=i;System.out.println(CaptureUtil.number+“:“+device.getDescription();CaptureUtil.StopCapturePacket();i+;);comboBox.addItemListener(new ItemListener() public void itemStateChanged(ItemEvent arg0) );toolBar.add(comboBox);JButt
37、on button_1 = new JButton(“u5F00u59CBu6293u5305“);button_1.setAction(action_1);toolBar.add(button_1);JButton button_2 = new JButton(“停止抓包 “);button_2.setAction(action_2);button_2.addActionListener(new ActionListener() public void actionPerformed(ActionEvent arg0) );toolBar.add(button_2);JButton butt
38、on_3 = new JButton(“u6E05u7A7Au8BB0u5F55“);button_3.addActionListener(new ActionListener() public void actionPerformed(ActionEvent e) );button_3.setAction(action_3);toolBar.add(button_3);Border brd=BorderFactory.createMatteBorder(1, 1, 2, 2, Color.black);list.setBorder(brd);list.addListSelectionList
39、ener(new ListSelectionListener()public void valueChanged(ListSelectionEvent arg0) / TODO Auto-generated method stubtextArea.setText(“);textArea.append(String)PacketMatch.hm.get(list.getSelectedIndex();/以下两行用于检测/ System.out.println(list.getSelectedIndex();/System.out.println(String)PacketMatch.hm.get
40、(list.getSelectedIndex(););jsp1.setBounds(5, 28, 258, 343);contentPane.add(jsp1);jsp2.setBounds(263, 28, 408, 343);contentPane.add(jsp2);textArea_1.setBounds(5, 371, 666, 67);contentPane.add(textArea_1);ArrayList alldevs=CaptureUtil.CaptureNet();for (PcapIf device : alldevs) comboBox.addItem(device.
41、getDescription();private class SwingAction extends AbstractAction public SwingAction() putValue(NAME, “选择网卡“);putValue(SHORT_DESCRIPTION, “Some short description“);public void actionPerformed(ActionEvent e) ArrayList alldevs=CaptureUtil.CaptureNet();if(alldevs!=null)System.out.println(“Network devic
42、es has been found:“);int i = 1;for (PcapIf device : alldevs) System.out.println(“第“+(i+)+“个网卡名字:“+device.getName()+“n 信息:“+device.getDescription();private class SwingAction_1 extends AbstractAction public SwingAction_1() putValue(NAME, “开始抓包“);putValue(SHORT_DESCRIPTION, “Some short description“);pu
43、blic void actionPerformed(ActionEvent e) /抓包线程(new CaptureUtil().start();private class SwingAction_2 extends AbstractAction public SwingAction_2() putValue(NAME, “停止抓包“);putValue(SHORT_DESCRIPTION, “Some short description“);public void actionPerformed(ActionEvent e) CaptureUtil.StopCapturePacket();t
44、extArea_1.setText(“);String message=“Tcp:“+PacketMatch.numberOfTcp+“包 “+PacketMatch.totalOfTcp+“KB “+“Udp:“+PacketMatch.numberOfUdp+“包 “+PacketMatch.totalOfUdp+“KB “+“n“+“Icmp:“+PacketMatch.numberOfIcmp+“包 “+PacketMatch.totalOfIcmp+“KB “+“Arp:“+PacketMatch.numberOfArp+“包 “+PacketMatch.totalOfArp+“KB
45、 “+“n“+“广播数据包“+PacketMatch.numberOfWideSpread+“包“+“ “+PacketMatch.totalOfSpread+“KB “+“总流量:“+PacketMatch.totalOfIp+“MB“;textArea_1.append(message);private class SwingAction_3 extends AbstractAction public SwingAction_3() putValue(NAME, “清空记录“);putValue(SHORT_DESCRIPTION, “Some short description“);pu
46、blic void actionPerformed(ActionEvent e) CaptureUtil.ClearPacket();第 4 章 运行结果第 5 章 心得体会通过这次实验我对于 TCP、UPD、ICMP、ARP、广播数据包等包的结构有了更好的认识。对于电脑上底层的发包与抓包也有了一定的认识。然后就是对用 Eclipse 进行编写 Java 程序有了更深的体会。Java 是一个成熟的语言,Eclipse 是一个比较完善的工具,对于各个方面知识的应用编写都有一定的基础支持。例如这次编写,Eclips 就通过 jnetpcap 很好的衔接了 winpcap的借口功能。另外,在界面编写
47、上,windowbuilder 也非常好用。这是一种可视化的编程,可以直接拖拉各种部件,在容器内进行布局。然后对于各个部件事件的添加也是很方便,这加快了程序的开发过程。嗯,这次的实验对于我来说不是很难,感觉这主要是前人种树,后人乘凉。很多东西都已经有了很完善的工具和结构。而现阶段我所能学习的感觉无非是对于各种语言工具、各种插件、框架的使用,对于这些前人们编写的东西掌握到一定的程度,以方便以后自行开发自己的一些工具。觉得课设就是一个学习过程。我在前人走过的路上学习着,避免走太多的弯路。在另一方面,也在路上不断积累,好在以后可以厚积薄发,有点自己的东西。另外还体会到了一点,就是用户需求和程序员实现功能的矛盾。由于用户需求不明确,或者说语意上描述的模糊,一名程序员很难写出百分百符合用户需要的程序。我感觉这方面我能做的就是提高自己程序的可扩展性,在用户需要一些其它的功能时,能对于程序进行功能的扩展。例如,最后的那流量大小的统计数目就是后来根据老师的要求添加上去的。总之这次课设让我对于之前我学过的一些知识计算机网络、Java 等再一次复习,然后进行了一次综合的运用,加深了我对它们的认知,也接触到了一些以前没用过的工具,感觉受益匪浅吧!