收藏 分销(赏)

用JAVA和SNMP实现流量统计.docx

上传人:仙人****88 文档编号:11398033 上传时间:2025-07-21 格式:DOCX 页数:7 大小:161.23KB 下载积分:10 金币
下载 相关
用JAVA和SNMP实现流量统计.docx_第1页
第1页 / 共7页
用JAVA和SNMP实现流量统计.docx_第2页
第2页 / 共7页


点击查看更多>>
资源描述
用JAVA和SNMP实现流量统计(二) 计算流量统计的思路是:采集两次设备数据,用流量值的差值,除以时间的差值,即是当前的流量值,时间间隔我用的是5秒。这里需要注意的是,时间间隔不能太长。我们可以计算一下: 2^32*2^3/(1024*1024*1024)=32   OID采集的是字节,要换成bit 也就是说,OID值最多累积到32Gbit就会归零。对于一般的千兆级的网络设备来说,5秒的时间,最多也就累积5~6.25Gbit的流量,但对于万兆级的设备来说,5秒的时间,可能累积超过50Gbit的流量,这将导致OID值发生一次或两次归零,这就情况下,就要缩短间隔时间了,3秒就更适合一些。其实采集数据的间隔时间越短,就越容易采集到峰值,时间越长,计算出来的数据就越平均。由于我们还没有哪个设备的端口流量能在5秒内超过32Gbit,选5秒做为时间间隔还是很适合的。采集OID值的代码如下: import java.io.IOException; import .InetAddress; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Vector; import org.snmp4j.AbstractTarget; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.UdpAddress; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; //统计流量的类,取时间与流量 public class Flow { final String OCTER_STRING = "admin";// 共同体 final String TIME_OID = ".1.3.6.1.2.1.1.3.0";// 时间OID,所有设备一样 String IpAddress;// 设备IP地址 ArrayList<String> FlowOidGroup;// 流量OID,可能有多个 private String NowTime;// 端口流量的采集时间 private long FlowValue;// 端口流量的值 public boolean isSuccess = true; // 构造器:IP地址和流量OID组(因为可能需要多个端口的流量加在一起) public Flow(String IpAddress, ArrayList<String> FlowOidGroup) { this.IpAddress = IpAddress; this.FlowOidGroup = FlowOidGroup; this.calc(); } // 取当前时间 public String getNowTime() { return NowTime; } // 取端口流量 public long getFlowValue() { return FlowValue; } // 计算端口流量 @SuppressWarnings("unchecked") private void calc() { try { Snmp snmp; TransportMapping transport; Address targetAddress = GenericAddress.parse("udp:" + IpAddress + "/161"); transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen();// 监听 CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(OCTER_STRING));// 设置共同体名 target.setAddress(targetAddress);// 设置目标Agent地址 target.setRetries(2);// 重试次数 target.setTimeout(3000);// 超时设置 target.setVersion(1);// 版本 PDU request = new PDU(); request.setType(PDU.GET);// 操作类型GET request.add(new VariableBinding(new OID(TIME_OID)));// OID_sysUpTime for (String FlowOid : FlowOidGroup) { request.add(new VariableBinding(new OID(FlowOid))); } // 取两次数据,间隔10秒,算差值 long[] time = new long[2]; long[][] flow = new long[2][FlowOidGroup.size()]; for (int count = 0; count < 2; count++) { ResponseEvent respEvt = snmp.send(request, target);// 发送请求 if (respEvt != null && respEvt.getResponse() != null) { // 从目的设备取值,得到Vector Vector<VariableBinding> revBindings = (Vector<VariableBinding>) respEvt.getResponse().getVariableBindings(); String TimeTicks = revBindings.elementAt(0) .getVariable().toString().trim(); String[] TimeString = TimeTicks.split(" ");// 得到时间字符串数组 // 取时间 186 days, 21:26:15.24,也有可能没有day,就是不到一天 if(TimeTicks.contains("day")){ time[count] = Long.parseLong(TimeString[0]) * 24 * 3600 + Long.parseLong(TimeString[2].split(":")[0]) * 3600 + Long.parseLong(TimeString[2].split(":")[1]) * 60 + Math.round(Double.parseDouble(TimeString[2] .split(":")[2])); }else{ time[count] = Long.parseLong(TimeString[0].split(":")[0]) * 3600 + Long.parseLong(TimeString[0].split(":")[1]) * 60 + Math.round(Double.parseDouble(TimeString[0] .split(":")[2])); } // 取端口流量 for (int i = 0; i < FlowOidGroup.size(); i++) { flow[count][i] = Long.parseLong(revBindings .elementAt(i + 1).getVariable().toString()); } isSuccess = true; } else { isSuccess = false; } if (count == 0) Thread.sleep(5000);// 延时5秒后,第二次取值 } snmp.close(); transport.close(); // 计算并为时间和最终流量赋值 Calendar c = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); NowTime = sdf.format(c.getTime());// 当前时间 long AllSubValue = 0; for (int i = 0; i < FlowOidGroup.size(); i++) { long sub = flow[1][i] - flow[0][i]; /*  * 端口流量值为无符号32位,超出后就归0,所以如果两次取值差值为负,  * 必然出现一次归0的情况,由于单个端口的流量不可能超过每5秒1*2^32字节  */ if (sub < 0) { // 因为端口流量为无符号32位,所以最大值是有符号32位的两倍 sub += 2L * Integer.MAX_VALUE; } AllSubValue += sub; } if (time[1] - time[0] != 0) { // 字节换算成兆比特才是最终流量 FlowValue = (long)(AllSubValue / 1024.0 / 1024 * 8 / (time[1] - time[0]));isSuccess = true; } else { System.out.println("地址:" + IpAddress + "数据采集失败!"); isSuccess = false; } } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } 程序的完善 以上只是单个设备的一次流量采集,接下来编写代码读取之前写好的配置文件,并根据文件内容生成Flow对象,再将采集到的数据插入到数据库,采集部分的工作就完成了。我写的代码采集周期是5分钟,与CACTI一样,共采集40多个设备。 可以写成控制台程序,也可以写成界面方式,用以显示设备的连接状态。 控制台程序如下:  界面程序如下: 还可以把界面程序隐藏到右下角: 报表程序 报表程序可以写成C/S架构,也可以写成B/S架构,它们各自的优势就不用说了。 用Delphi写的曲线图表 用Java EE+JBoss+JFreeChart写的报表和图表   PS:由于本人对Java EE的学习尚浅,所以Web程序的开发是我的一个同事个人完成的,他可是专业的。 至此,一个流量统计系统就完成了。在这个系统程序编写的过程中,我学到了很多知识,也思考并解决了不少以前不曾想过或遇过的问题。作为一名业余的编程爱好者,用自己的编程知识解决工作中的实际问题,不但更增加了自己的学习动力,也为自己和同事节省出更多的时间,真是一件让人快乐的事!
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 通信科技 > 开发语言

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服