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正在學,還行學完,代碼冗余嚴重,
本博客僅僅提供解決方法!歡迎討論,感謝批評指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/550113.html
標籤:其他
上一篇:STL容器之queue
下一篇:品味布隆過濾器的設計之美