Java + Jpcap实现监控 IP包流量
Posted fwdba
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java + Jpcap实现监控 IP包流量相关的知识,希望对你有一定的参考价值。
Java + Jpcap实现监控 IP包流量
说明:本设计是计算机网络课程的课设,因为代码是提前实现的,本博客于后期补上,又因为代码没写注释自己也看不懂了,所以,仅供参考,就当提供一种实现方式。
文中提供的《Jpcap中文API文档》来源于网络,本文仅用于学习交流,如有侵权,可联系我进行删除。
效果图:
1)课程设计要求
1.1 课程设计目的
通过本实课程设计,有助于理解 IP包的格式和加深对 IP 协议的理解。
1.2 课程设计要求
编制程序,监控网络,捕获一段时间内网络上的 IP 数据包,按 IP 数据包的源地址统计出该源地址在该时间段内发出的 IP 包的个数,将其写人日志文件中或用图形表示出来(建议用图形表示出统计结果)。
1.3 程序的具体要求如下
用命令行运行: IPStatistic time logfile
其中, IPStatistic 是程序名; time 是设定的统计时间间隔(单位为分钟,比如,2表示2分钟); logfile 表示统计结果写人的日志文件名(若用图形表示统计结果则可以不选这个参数)。
2)编码前的准备
2.1 技术点
后端:springboot,Jpcap
前端:vue2,ECharts
说明:Jpcap是一个能够捕获、发送网络数据包的java类库包。
2.2 环境搭建
2.2.1 事先说明和下载链接
ps:网上大部分都是
Jpcap
+winpcap
,但是winpcap
太老了,大概率在Windows10和Windows11上会出问题,当时也踩了不少坑,这里推荐使用npcap
winocap网址:https://www.winpcap.org/
Npcap网址:https://npcap.com/
从图中可以看出,winocap已经不再支持,推荐使用npcap
进入Npcap官网下载即可
2.2.2 资源下载
链接:https://pan.baidu.com/s/1y6u-V-FPwOgIxC9ZoAD7yg
提取码:1111
内容:
- Jpcap中文API文档
- npcap-1.72.exe
- Jpcap.dll
- jpcap.jar
- network_vue(前端代码,需要自己装包:
npm install
) - network_course_design(Java代码)
2.2.3安装
重点1、3、4步
-
Npcap.exe正常进行安装即可
-
创建一个普通springboot项目
-
在项目中导入
Jpcap.jar
包
-
将
Jpcap.dll
放到JDK安装路径下的 /jre/bin 目录下(我这里好像没有放也可以运行,可以试一下) -
前端就是一个普普通通的VUE+ECharts项目
3)编码
重要提示:当时为了赶工,其中的逻辑很有问题,现在的评价就一个字,烂,非常烂!!!看看关键实现就行。
这里推荐看这篇博客,写的很好,里面对重要字段进行了说明:https://www.cnblogs.com/shy-huiying/p/5636274.html
3.1 后端实现
3.1.1 获得本机所有网卡接口信息
Jpcap提供了方法JpcapCaptor.getDeviceList()
完成这个任务,该方法返回一组NetworkInterface对象。
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
/**
* 这里是controller层
* 获得所有网卡接口
* @return List<String>
*/
@RequestMapping("/info")
public Object getNetworkCard()
// 获取网络接口列表,返回所有的网络设备数组;
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
if (devices.length == 0)
return "无网卡信息";
else
List<NetworkCardPojo> netList = new ArrayList<>();
int index = 0;
for (NetworkInterface n : devices)
//NetworkCardPojo是自己编写的实体类,包含网卡接口索引和网卡接口名两个属性
NetworkCardPojo networkCardPojo = new NetworkCardPojo();
networkCardPojo.setIndex(index++);
networkCardPojo.setDescription(n.description);
//networkCardPojo.setNetworkInterface(n);
netList.add(networkCardPojo);
return netList;
public class NetworkCardPojo
private Integer index;
private String description;
//private NetworkInterface NetworkInterface;
返回到前端的数据:
3.1.2 得到指定网卡的具体信息
- NetworkInterface[] devices = JpcapCaptor.getDeviceList();得到多有网卡信息
- devices[index].addresses;根据前端传入的网卡接口索引得到指定网卡接口的信息。
/**
* 这里是controller层
* 打印选择网卡的IP地址和子网掩码;
* @param index
* @return
*/
@RequestMapping("/local")
public LocalParameterPojo getLocalParameter(@ProbeParam("index") Integer index)
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//根据传入的网卡索引获取该网卡接口所属的IP地址
NetworkInterfaceAddress[] device = devices[index].addresses;
//LocalParameterPojo是自己编写的实体类,包含本机IP地址、子网掩码、网络连接类型
LocalParameterPojo local = new LocalParameterPojo();
if (device.length>0)
local.setIpv4(device[0].address);
local.setSubnetMask(device[0].subnet);
local.setNetType(devices[0].datalink_description);
else
local.setNetType("该网卡接口不可用,请尝试切换其他网卡接口!");
return local;
LocalParameterPojo实体类,注意部分字段是InetAddress
类型
public class LocalParameterPojo
private InetAddress ipv4; //本机IP地址
private InetAddress SubnetMask; //子网掩码
private String netType; //网络连接类型
3.1.3 监控ip包数据
因为一个ip地址会发送多个ip包,这里主要是将ip包进行分组统计:
IP地址--累计IP包数量--累计IP包大小
这里写的不好,有些问题,甚至问题很大,后面想到有更好的解决方法,但是没有尝试过,就不写了
/**
* 这里是controller层
* 开启监控ip包流量监控
* @param index
* @return
*/
@RequestMapping("/start")
public List<TargetParameterPojo> startGetPacket(@ProbeParam("index") Integer index)
targetParameter.startThread(index);
//根据Ip地址分组
Map<InetAddress, IpGroup> mapAll = new HashMap<>();
System.out.println("ip count:"+targetParameter.getTargetMap().size());
for (int i=0;i<targetParameter.getTargetMap().size();i++)
IpGroup ipGroup = new IpGroup();
for (InetAddress key:targetParameter.getTargetMap().get(i).keySet())
Integer size = targetParameter.getTargetMap().get(i).get(key);
int count=1;
//检查 hashMap 中是否存在指定的 key 对应的映射关系。
if(mapAll.containsKey(key))
Integer tempSize = mapAll.get(key).getSize();
size += tempSize;
Integer tempCount = mapAll.get(key).getCount();
count += tempCount;
ipGroup.setCount(count);
ipGroup.setSize(size);
mapAll.put(key,ipGroup);
// 将数据装到TargetParameterPojo
List<TargetParameterPojo> targetList = new ArrayList<>();
for (Map.Entry<InetAddress,IpGroup> map:mapAll.entrySet())
TargetParameterPojo targetPojo = new TargetParameterPojo();
targetPojo.setSourceIp(map.getKey());
targetPojo.setSize(map.getValue().getSize());
targetPojo.setCount(map.getValue().getCount());
targetList.add(targetPojo);
return targetList;
/**
* 关闭监控ip包流量
* @return
*/
@RequestMapping("/stop")
public int stopsGetPacket()
int flag = targetParameter.getTargetMap().size();
if(flag>1)
targetParameter.stopThread();
return 1;
else
return 0;
service层
@Service
public class TargetParameter implements Runnable
//数据统计要用到的list
private static List<Map<InetAddress,Integer>> targetMap = new ArrayList<>();
private boolean flag = true;
private TargetParameter tp;
private Thread thread;
private Integer isOff=0;
public TargetParameter(JpcapCaptor jpcap)
this.jpcap = jpcap;
private JpcapCaptor jpcap = null;
public TargetParameter()
public List<Map<InetAddress, Integer>> getTargetMap()
return targetMap;
@Override
public void run()
//只要不停止就一直进行抓包
while (flag)
IPPacket ipPacket = (IPPacket) jpcap.getPacket();
if (ipPacket!=null)
Map<InetAddress,Integer> map = new HashMap<>();
map.put(ipPacket.src_ip,ipPacket.len);
targetMap.add(map);
// 回调方法
//jpcap.processPacket(-1, new CallbackService());
/**
* 开启线程方法
*/
public void startThread(Integer index)
if (isOff==0)
try
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//获得了JpcapCaptor实例就可以用来捕获来自网络接口的数据包。
//网卡索引,捕获数据包大小,是否开启混杂模式(混杂模式会捕获到数据表),超时
jpcap = JpcapCaptor.openDevice(devices[index], 1024, true, 1000);
// 在捕获前先设置过滤;
jpcap.setFilter("ip", true);
catch (IOException e)
e.printStackTrace();
System.out.println("抓取数据包时出现异常!!");
tp = new TargetParameter(jpcap);
//创建一个抓抓包线程,保证一直进行抓包
thread = new Thread(tp);
thread.start();
System.out.println("thread.getName():"+thread.getName());
isOff++;
/**
* 关闭线程并清空List
*/
public void stopThread()
isOff=0;
tp.flag=false;
targetMap.clear();
System.out.println(targetMap);
Pojo:
public class TargetParameterPojo
private InetAddress sourceIp;
private Integer count;
private Integer size;
public class IpGroup
private Integer size;
private Integer count;
3.1.4 目录结构
3.2 前端实现
前端实现很简单,主要是数据渲染,这里说一下我的思路:
- 设定一个计时器,每隔1秒钟就请求一次数据,从而进行数据更新(axios实现)
- 可根据需要对数据进行排序和截取,比如截取前20条数据进行排序(数据条数太多会造成图形不美观)
- 优化:对开启和关闭按钮进行控制,防止重复请求和重复关闭
4)END
资源下载
链接:https://pan.baidu.com/s/1y6u-V-FPwOgIxC9ZoAD7yg
提取码:1111
内容:
- Jpcap中文API文档
- npcap-1.72.exe
- Jpcap.dll
- jpcap.jar
- network_vue(前端代码,需要自己装包:
npm install
) - network_course_design(Java代码)
重要:请勿学习如上代码的写法,那时候vue正在学,还行学完,代码冗余严重。
本博客仅仅提供解决方法!欢迎讨论,感谢批评指正。
iptraf:一个实用的TCP/UDP网络监控工具
iptraf是一个基于ncurses的IP局域网监控器,用来生成包括TCP信息、UDP计数、ICMP和OSPF信息、以太网负载信息、节点状态信息、IP校验和错误等等统计数据。
它基于ncurses的用户界面可以使用户免于记忆繁琐的命令行开关。
特征
- IP流量监控器,用来显示你的网络中的IP流量变化信息。包括TCP标识信息、包以及字节计数,ICMP细节,OSPF包类型。
- 简单的和详细的接口统计数据,包括IP、TCP、UDP、ICMP、非IP以及其他的IP包计数、IP校验和错误,接口活动、包大小计数。
- TCP和UDP服务监控器,能够显示常见的TCP和UDP应用端口上发送的和接收的包的数量。
- 局域网数据统计模块,能够发现在线的主机,并显示其上的数据活动统计信息。
- TCP、UDP、及其他协议的显示过滤器,允许你只查看感兴趣的流量。
- 日志功能。
- 支持以太网、FDDI、ISDN、SLIP、PPP以及本地回环接口类型。
- 利用Linux内核内置的原始套接字接口,允许它(指iptraf)能够用于各种支持的网卡上
- 全屏,菜单式驱动的操作。
安装方法
Ubuntu以及其衍生版本
sudo apt-get install iptraf
Arch Linux以及其衍生版本
sudo pacman -S iptra
Fedora以及其衍生版本
sudo yum install iptraf
用法
如果不加任何命令行选项地运行iptraf命令,程序将进入一种交互模式,通过主菜单可以访问多种功能。
简易的上手导航菜单。
选择要监控的接口。
接口ppp0处的流量。
以上是关于Java + Jpcap实现监控 IP包流量的主要内容,如果未能解决你的问题,请参考以下文章