此次的设计模式课程设计让我很是感觉到有些失败,原因是1:在开始定题是是研究yazd论坛,在参考了彭晨阳《java使用系统开发指南》一书,在第三章的Jlive论坛便是基于yazd论坛的升级版(相关可以参考解道论坛)。在和同伴一起调通admin部分后,后来自己花费1天多想弄通控制权限部分(因为他的进入yazd论坛普通用户需要注册还要激活,我们搞不同他的激活方式,便导致后期不能继续研究),想一想这也是我自己本身能力不足的一方面。虽然之前和老师一起做过相关的web项目,但是还是没有深入研究。
后来,小伙伴转到研究spring框架,我也不得不另择道路。想了想,还是重构一下自己原先的代码吧。所以选了《计算机网络课程设计》----局域网抓包的程序。在重构过程中我也感觉到自己写的代码是多么惨目忍睹。打开自己原来写的东西,才发现当时写的代码是多么不可理喻,类与类之间耦合度太强,两个类之间互相需要调用造成一种死锁局面(因为A类需要new时需要调用B类的一个方法,而B类new时有需要调用A类的方法);另外程序出现的问题就是面向实现而编程的,违背了面向对象的设计优点:面向接口编程。还记得前些日子,教授说的“软件的理解“,自己学了三年可以说尚未真正悟出他所说的。
总之自己还得继续努力!!!
下面就将自己这两天写的一些关于jentpcap分享给大家:
<1>架构模式:MVC
<2>工厂模式:通过反射生产对象,这个做法主要是参考和老师一起做的项目,通过读取可配置文件然后生产对象
package com.jnetpcap.util;
import java.util.Properties;
public class MyFactory {
public static Properties prop = new Properties();
/**2017/12/14
*通过反射获取对象,这里返回的是Object类型对象,然后强制转换便可以生产相应对象
*/
public static Object getObject(String name) {
try {
String className = prop.getProperty(name);
Object obj = Class.forName(className).newInstance();
return obj;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} catch (InstantiationException e) {
e.printStackTrace();
return null;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
}
<2>单例模式:程序中使用单例模式主要确保抓包的类只有一个实例,自己感觉写个单例有点多余,因为吸收了一些之前java课程设计中达内人员过来讲的IOC(依赖注入)模式就是new出一个对象,然后通过set方法注入对象。
package com.jnetpcap.service;
import java.awt.Frame;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import com.jnetpcap.entity.PacketMessage;
import com.jnetpcap.table.Buffer;
import com.jnetpcap.table.TableModel;
/*
*@author:软件工程:严治政
*@time=2017年9月14日
*/
public class CaptureSingleton implements Runnable{
List<PacketMessage> packetMessage ;
private final List<PcapIf> devs = new ArrayList<PcapIf>();
private final StringBuilder err = new StringBuilder();
private PcapIf device;
int num;
private volatile static CaptureSingleton instance ;
private MyPcapPacketHandler<Object> myhandler = new MyPcapPacketHandler<Object>();
public MyPcapPacketHandler<Object> getHander() {
return myhandler;
}
private CaptureSingleton() {
}
public static CaptureSingleton getInstance() {
if (instance == null) {
synchronized(CaptureSingleton.class) {
if(instance == null)
instance = new CaptureSingleton();
}
}
return instance;
}
// 获取机器上网卡列表
public List<PcapIf> getDevs() {
int r = Pcap.findAllDevs(devs, err);
if (r == Pcap.NOT_OK || devs.isEmpty()) {
JOptionPane.showMessageDialog(null, err.toString(),"error error error!"
,JOptionPane.ERROR_MESSAGE);
return null;
}else {
return devs;
}
}
//选择一个网卡开始抓包
public void startCaptureAt(int num) {
this.device = devs.get(num);
start(device);
}
public void start(PcapIf device) {
int snaplen = Pcap.DEFAULT_JPACKET_BUFFER_SIZE;
int flags = Pcap.MODE_PROMISCUOUS;
int timeout = 10*1000;
StringBuilder err = new StringBuilder();
Pcap pcap = Pcap.openLive(device.getName(), snaplen, flags, timeout, err);
if (pcap == null) {
JOptionPane.showMessageDialog(null, err.toString(),"error error error!",JOptionPane.ERROR_MESSAGE);
return ;
}
int cnt = 1;
//包匹配
pcap.loop(cnt,myhandler,"jnetpcap rock!");
pcap.close();
}
public void setNum(int num) {
this.num = num;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
/**
* 这个位置主要是我一开始在测试类中启动的是单列模式,而具体选择网卡是用num确定
* 一开始new出来这个类默认值是0号网卡,但是这个num我需要通过界面选择传过来
* 所以便直接给定网卡号码,后期需要在考虑考虑
*/
System.out.println(num+"号网卡工作");
startCaptureAt(3);
}
}
}
<3>策略模式:策略模式主要是完成一项任务,可以有多种方法,每一种方式成为一个策略
package com.jnetpcap.util;
import org.jnetpcap.packet.PcapPacket;
import com.jnetpcap.entity.Packet;
import com.jnetpcap.entity.PacketMessage;
/**
*
* @author
* @编辑时间:2018年3月11日
* @功能说明:策略模式接口
* @version:
*/
public interface IHanderStrategy {
public PacketMessage hander(PcapPacket p);
}
处理ip数据包
package com.jnetpcap.util;
import java.util.Date;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.protocol.network.Ip4;
import com.jnetpcap.entity.Packet;
import com.jnetpcap.entity.PacketMessage;
public class IPStrategy implements IHanderStrategy{
@Override
public PacketMessage hander(PcapPacket packet) {
Ip4 ip = new Ip4();
PacketMessage pm = new PacketMessage();
packet.getHeader(ip);
byte[] sIp = new byte[4];
byte[] dIp = new byte[4];
sIp = ip.source();
dIp = ip.destination();
String srcIp = org.jnetpcap.packet.format.FormatUtils.ip(sIp);
String dstIp = org.jnetpcap.packet.format.FormatUtils.ip(dIp);
pm.setsIp(srcIp);
pm.setdIp(dstIp);
pm.setCaplen(packet.getCaptureHeader().caplen());
pm.setTime(new Date(packet.getCaptureHeader().timestampInMillis()));
return pm;
}
}
处理Ethernet数据包
package com.jnetpcap.util;
import java.util.Date;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.protocol.lan.Ethernet;
import com.jnetpcap.entity.PacketMessage;
public class EthStrategy implements IHanderStrategy{
@Override
public PacketMessage hander(PcapPacket p) {
Ethernet eth = new Ethernet();
PacketMessage pm = new PacketMessage();
eth = p.getHeader(eth);
byte[] dstMac = eth.destination();
byte[] srcMac = eth.source();
int type = eth.type();
pm.setsMac(asString(srcMac));
pm.setdMac(asString(dstMac));
pm.setCaplen(p.getCaptureHeader().caplen());
pm.setTime(new Date(p.getCaptureHeader().timestampInMillis()));
return pm;
}
public String asString(byte[] mac) {
final StringBuilder buf = new StringBuilder();
for (byte b : mac) {
if (buf.length() != 0) {
buf.append(':');
}
if (b >= 0 && b < 16) {
buf.append('0');
}
buf.append(Integer.toHexString((b < 0) ? b + 256 : b).toUpperCase());
}
return buf.toString();
}
}
package com.jnetpcap.service;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.protocol.lan.Ethernet;
import org.jnetpcap.protocol.network.Ip4;
import com.jnetpcap.entity.PacketMessage;
import com.jnetpcap.util.EthStrategy;
import com.jnetpcap.util.IHanderStrategy;
import com.jnetpcap.util.IPStrategy;
/*
*@author:策略模式调用类
*@time=2017年9月14日
*/
public class PacketMatch {
private IHanderStrategy strategy;
public void setStrategy(IHanderStrategy strategy) {
this.strategy = strategy;
}
public PacketMessage algorithm(PcapPacket packet) {
return strategy.hander(packet);
}
//分析数据包 并返回一个packetMessage对象
public PacketMessage handlePacket(PcapPacket packet) {
PacketMessage pm = null;
/**********************************************
* 通过注入具体的配对策略实现分析不同的数据报
**********************************************/
if (packet.hasHeader(new Ip4() )) {
this.setStrategy(new IPStrategy() );
pm = this.algorithm(packet);
}
else if (packet.hasHeader(Ethernet.ID)) {
this.setStrategy(new EthStrategy());
pm = this.algorithm(packet);
}
return pm;
}
}