Java基于Snmp4j库实现SNMP协议的调用方式
作者:毒爪的小新
本文分两部分:首先确保主机与SNMP设备通信,需配置路由表以解决跨网段问题;其次介绍Java实现SNMP协议的简单操作及流量监控,涵盖依赖导入、连接参数设置、流量数据采集与日志记录
在进行SNMP
协议调用之前,要先保证主机和目的机器可以通信,可以用ping
工具来尝试连通性,如果可以通信,可直接跳转到第二章节和第三章节查看协议的调用;如果不能通信,即不在同一个网段,那么需要先按照第一章节的步骤设置路由表,再根据第二章节和第三章节的步骤实现协议的调用
1. 设置路由表
1.1 原理
如果windows
所在网段和lxd
容器【即SNMP
协议需要访问的设备】所在网段不一致,我们不能直接访问,则需要进行路由表的设置
以如下ip
地址为例,进行路由表的设置,其中
windows
的ip
地址为192.168.31.224
Linux
服务器的ip
地址为192.168.31.104
Linux
服务器中lxd
容器的ip
地址为10.137.5.86
,网关地址通过route -n
查看后得知为10.137.5.1
所以思路为:
每当windows
访问容器的时候,将流量转发到服务器中
同理,容器回复windows
的时候,因为网关本身可以和服务器连通,所以流量转发到网关中即可
1.2 设置
windows
中的设置
# 查看路由表 route print # 将访问ip地址为10.137.5.86,且掩码为255.255.255.255的流量转发到192.168.31.104中 route add 10.137.5.86 mask 255.255.255.255 192.168.31.104 # 删除路由表 route delete 10.137.5.86 mask 255.255.255.255 192.168.31.104
lxd
容器中的设置
# 查看路由表 ip route # 将访问ip地址为192.168.31.224/32的流量转发到10.137.5.1中 ip route add 192.168.31.224/32 via 10.137.5.1 # 删除路由表 ip route del 192.168.31.224/32 via 10.137.5.1
此时,我们才可以保证windows
访问lxd
容器
2. Java实现SNMP简单操作
2.1 导入依赖
<dependency> <groupId>org.snmp4j</groupId> <artifactId>snmp4j</artifactId> <version>2.8.15</version> </dependency>
2.2 设置连接
建立一个类来存储常见oid
//定义snmp类,存储常量 public class MySnmp { //设备描述信息 public final String Sys_Desc = "1.3.6.1.2.1.1.1"; //设备开启时间 public final String Sys_Up_Time = "1.3.6.1.2.1.1.5"; //设备名称 public final String Sys_Name = "1.3.6.1.2.1.1.3"; //网卡接口速率 public final String If_Speed = "1.3.6.1.2.1.2.2.1.5.126"; //网卡接口当前时刻进流量 public final String If_In_Octets = "1.3.6.1.2.1.2.2.1.10.126"; //网卡接口当前时刻出流量 public final String If_Out_Octets = "1.3.6.1.2.1.2.2.1.16.126"; }
建立连接以及传参函数
//用来获取设备信息 public class GetMessage { public String getMessageByIpAndOid(String ip,String oid) throws IOException { String result = null ; // 1. 创建 SNMP 管理器 CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("public")); target.setAddress(GenericAddress.parse("udp:"+ip+"/161")); target.setRetries(2); target.setTimeout(1000); TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping(); Snmp snmp = new Snmp(transport); snmp.listen(); // 2. 创建 OID OID oid1 = new OID(oid); // 3. 发送 SNMP 请求并处理响应 PDU pdu = new PDU(); pdu.add(new VariableBinding(oid1)); pdu.setType(PDU.GETNEXT); ResponseEvent event = snmp.send(pdu, target); PDU response = event.getResponse(); if (response == null) { System.out.println("没有得到响应"); } else { result = String.valueOf(response.get(0).getVariable()); } // 4. 关闭 SNMP 管理器 snmp.close(); return result; } }
2.3 测试获取信息
public class Test { public static void main(String[] args) throws IOException { MySnmp mySnmp = new MySnmp(); GetMessage getMessage = new GetMessage(); System.out.println("获取容器信息:"+getMessage.getMessageByIpAndOid("10.137.5.86",mySnmp.Sys_Desc)); System.out.println("获取容器名称:"+getMessage.getMessageByIpAndOid("10.137.5.86",mySnmp.Sys_Name)); System.out.println("获取容器开启时长:"+getMessage.getMessageByIpAndOid("10.137.5.86",mySnmp.Sys_Up_Time)); System.out.println("获取容器eth0网口当前速率:"+getMessage.getMessageByIpAndOid("10.137.5.86",mySnmp.If_Speed)); System.out.println("获取容器eth0网口当前时刻进流量:"+getMessage.getMessageByIpAndOid("10.137.5.86", mySnmp.If_In_Octets)); System.out.println("获取容器eth0网口当前时刻出流量:"+getMessage.getMessageByIpAndOid("10.137.5.86", mySnmp.If_Out_Octets)); } }
3. Java实现SNMP流量监控
第二章节实现了利用snmp
的简单操作,本章节介绍如何实现流量监控
思路如下:
- 创建
io
流用来写入日志文件 for
循环连续读取当前时刻流量- 利用线程进行休眠来控制读取时间间隔
- 将流量写入日志文件并且刷新
//实现流量监控 public class TrafficMonitoring { public void getTrafficMonitoring(int time) throws IOException { //获取oid MySnmp mySnmp = new MySnmp(); //输入流 FileOutputStream fos = null; OutputStreamWriter writer = null; BufferedWriter bf = null; //根据oid获取结果 GetMessage getMessage = new GetMessage(); try { //表示内容的追加 fos = new FileOutputStream("src/main/java/org/example/logFile.log",true); writer = new OutputStreamWriter(fos); bf = new BufferedWriter(writer); bf.write("====================切割线==========================\n"); //格式化当前时间 SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0 ; i<time ; i++) { Date date = new Date(System.currentTimeMillis()); //获得当前时间 String nowTime = formatter.format(date); //活得当前流量 String If_In_Octets = getMessage.getMessageByIpAndOid("10.137.5.86", mySnmp.If_In_Octets); String If_Out_Octets = getMessage.getMessageByIpAndOid("10.137.5.86", mySnmp.If_Out_Octets); bf.write(nowTime+"-"+"If_In_Octets:"+If_In_Octets+"bytes,If_Out_Octets:"+If_Out_Octets+"bytes\n"); Thread.sleep(1000); } bf.flush(); System.out.println(time+"秒内的流量监控完毕,请查看日志文件"); } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { if (fos != null) { fos.close(); } if (writer != null) { writer.close(); } if (bf != null) { bf.close(); } } } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。