重要的类和接口
Snmp类:该类是SNMP4J中最为核心的类。负责SNMP报文的接受和发送。
PDU类和ScopedPDU类:该类是SNMP报文单元的抽象,其中PDU类适用于SNMPv1和SNMPv2c。ScopedPDU类继承于PDU类,适用于SNMPv3。
Target接口和UserTarget类:对应于SNMP代理的地址信息,包括IP地址和端口号(161)。其中Target接口适用于SNMPv1和SNMPv2c。UserTarget类实现了Target接口,适用于SNMPv3。
TransportMapping接口:该接口代表了SNMP4J所使用的传输层协议。这也是SNMP4J一大特色的地方。按照RFC的规定,SNMP是只使用UDP作为传输层协议的。而SNMP4J支持管理端和代理端使用UDP或者TCP进行传输。该接口有两个子接口。
两种消息发送模式
SNMP4J支持两种消息发送模式:同步发送模式和异步发送模式。
其中同步发送模式也称阻塞模式。当管理端发送出一条消息之后,线程会被阻塞,直到收到对方的回应或者时间超时。同步发送模式编程较为简单,但是不适用于发送广播消息。
异步发送模式也称非阻塞模式。当程序发送一条消息之后,线程将会继续执行,当收到消息的回应的时候,程序会对消息作出相应的处理。要实现异步发送模式,需要实例化一个实现了ResponseListener接口的类的对象。ResponseListener接口中有一个名为onResponse的函数。这是一个回调函数,当程序收到响应的时候,会自动调用该函数。由该函数完成对响应的处理。
实现管理端的总体步骤
该部分说明了利用SNMP4J编写SNMP管理端的大致过程,读者在阅读之后会对SNMP4J有一个宏观上的认识。在附录部分,作者给出了一个用SNMP4J开发管理站的样例程序,如果有进一步的需要,请参考附录部分。
初始化
明确SNMP在传输层所使用的协议
一般情况下,我们都使用使用UDP协议作为SNMP的传输层协议,所以我们需要实例化的是一个DefaultUdpTransportMapping接口对象;
实例化一个snmp对象
在此过程中,我们需要将1中实例化的DefaultUdpTransportMapping接口的对象作为参数,穿snmp类的构造函数中。
另外,如果实现的SNMPv3协议,我们还需要设置安全机制,添加安全用户等等;
监听snmp消息
在此,我们可以调用刚刚实例化的DefaultUdpTransportMapping的接口对象的listen方法,让程序监听snmp消息;
构造发送目标
如果实现的是SNMPv3程序,则需要实例化一个UserTarget对象,如果实现的是SNMPv2c或者说SNMPv1,则需要实例化一个CommunityTarget对象。
之后,我们还需要对实例化的对象做一些设置。如果是CommunityTarget的对象,则需要设置版本,重传时间和等待时延。如果是UserTarget对象,我们不仅需要设置版本、重传时间、等待时延,还需要设置安全级别和安全名称。
构造发送报文
如果发送的是SNMPv3的报文,我们则需要实例化一个ScopedPDU 类的对象,否则我们需要实例化一个PDU类的对象。之后,我们还需要生成一个OID对象,其中包含了我们所需要获取的SNMP对象在MIB库中的ID。然后我们需要将OID和之前生成的PDU对象或者是ScopedPDU对象绑定,并且设置PDU的报文类型(五种SNMP报文类型之一)。
构造响应监听对象(异步模式)
当使用异步模式的时候,我们需要实例化一个实现了ResponseListener
的对象,作为响应消息的监听对象。在构造该对象的过程中,我们需要重写ResponseListener的OnResponse函数,该函数是一个回调函数,用来处理程序收到响应后的一些操作。
发送消息
当所有上述操作都设置完毕之后,就可以发送消息了。同步模式和异步模式发送消息调用的函数名字均为send,但是两个函数所需参数不一样。同步模式的参数仅为4.3.2和4.3.3中构造的目标对象和报文对象,而异步模式还需要4.3.4中构造的监听对象。
同步模式发送消息后便等待响应的到达,到达之后会返回一个ResponseEvent对象,该对象中包含了响应的相应信息。
异步模式发送消息之后便会继续执行,当收到响应消息时便会调用监听对象的OnResponse函数。该函数中的语句便是我们对响应的处理!
我们来进行一个同步的GET操作,假如你已经有了可以访问的端口:
package t1; import java.io.IOException; import java.util.Vector; 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.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; /** * @说明 SNMP4J测试 * @author cuisuqiang * @version 1.0 * @since */ public class SnmpUtil { private Snmp snmp = null; private Address targetAddress = null; public void initComm() throws IOException { // 设置Agent方的IP和端口 targetAddress = GenericAddress.parse("udp:192.168.0.148/22500"); TransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } public ResponseEvent sendPDU(PDU pdu) throws IOException { // 设置 目标 CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("public")); target.setAddress(targetAddress); // 通信不成功时的重试次数 N+1次 target.setRetries(2); // 超时时间 target.setTimeout(2 * 1000); // SNMP 版本 target.setVersion(SnmpConstants.version2c); // 向Agent发送PDU,并返回Response return snmp.send(pdu, target); } public void getPDU() throws IOException { // PDU 对象 PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID("1.2.3.4.5.6"))); // 操作类型 pdu.setType(PDU.GET); ResponseEvent revent = sendPDU(pdu); if(null != revent){ readResponse(revent); } } @SuppressWarnings("unchecked") public void readResponse(ResponseEvent respEvnt) { // 解析Response System.out.println("------------>解析Response<-------------"); if (respEvnt != null && respEvnt.getResponse() != null) { Vector<VariableBinding> recVBs = respEvnt.getResponse() .getVariableBindings(); for (int i = 0; i < recVBs.size(); i++) { VariableBinding recVB = recVBs.elementAt(i); System.out.println(recVB.getOid() + " : " + recVB.getVariable().toString()); } } } public static void main(String[] args) { try { SnmpUtil util = new SnmpUtil(); util.initComm(); util.getPDU(); } catch (IOException e) { e.printStackTrace(); } } }
我的被管设备返回了:
------------>解析Response<------------- 0.0 : xxx 1.3.6.1.2.1.1.6.0 : 12345 1.3.6.1.2.1.1.2.0 : 54321
这个GET操作我们只发送了一个OID过去,但是你不能确定会收到多少OID的数据,因为这是双方约定的而不是协议定死的!
消息发送后会产生等待,如果超时时间内没有响应则直接过去!
那么异步是怎样实现的呢?其实很简单,只需对上面代码简单修改:
package t1; import java.io.IOException; import java.util.Vector; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; 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.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; /** * @说明 SNMP4J测试 * @author cuisuqiang * @version 1.0 * @since */ public class SnmpUtil { private Snmp snmp = null; private Address targetAddress = null; public void initComm() throws IOException { // 设置Agent方的IP和端口 targetAddress = GenericAddress.parse("udp:192.168.0.148/22500"); TransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); } public ResponseEvent sendPDU(PDU pdu) throws IOException { // 设置 目标 CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("public")); target.setAddress(targetAddress); // 通信不成功时的重试次数 N+1次 target.setRetries(2); // 超时时间 target.setTimeout(2 * 1000); // SNMP 版本 target.setVersion(SnmpConstants.version2c); // 设置监听对象 ResponseListener listener = new ResponseListener() { public void onResponse(ResponseEvent event) { System.out.println("---------->开始异步解析<------------"); readResponse(event); } }; // 发送报文 snmp.send(pdu, target, null, listener); return null; } public void getPDU() throws IOException { // PDU 对象 PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID("1.2.3.4.5.6"))); // 操作类型 pdu.setType(PDU.GET); ResponseEvent revent = sendPDU(pdu); if(null != revent){ readResponse(revent); } } @SuppressWarnings("unchecked") public void readResponse(ResponseEvent respEvnt) { // 解析Response System.out.println("------------>解析Response<-------------"); if (respEvnt != null && respEvnt.getResponse() != null) { Vector<VariableBinding> recVBs = respEvnt.getResponse() .getVariableBindings(); for (int i = 0; i < recVBs.size(); i++) { VariableBinding recVB = recVBs.elementAt(i); System.out.println(recVB.getOid() + " : " + recVB.getVariable().toString()); } } } public static void main(String[] args) { try { SnmpUtil util = new SnmpUtil(); util.initComm(); util.getPDU(); } catch (IOException e) { e.printStackTrace(); } } }
被管设备返回的内容是一样的,但是我们的控制台打印不太一样:
---------->开始异步解析<------------ ------------>解析Response<------------- 0.0 : xxx 1.3.6.1.2.1.1.6.0 : 12345 1.3.6.1.2.1.1.2.0 : 54321
因为我们采用了异步模式!
那么如何SET呢?
我们只需要把操作类型改为SET,然后在UDP中设置参数即可:
pdu.add(new VariableBinding(new OID("1.2.3.4.5.6"),new OctetString("priv"))); // 操作类型 pdu.setType(PDU.SET);
这里我们传递了一个字符串!打开SNMP4J源码或API,我们看到:
/** * Creates an octet string from a java string. * * @param stringValue * a Java string. */ public OctetString(String stringValue) { this.value = stringValue.getBytes(); }
然后我们在源码中还能看到这样的构造函数:
/** * Creates an octet string from an byte array. * @param rawValue * an array of bytes. */ public OctetString(byte[] rawValue) { this(rawValue, 0, rawValue.length); }
其实很简单,因为SNMP4J本身发送的就是一组字节流,你设置的字符串其实在构造中还是获得了这个字符串的字节流信息,其实你完全可以设置一个字节流进去!
所以,对于OID的参数,简单来说就是一组BYTE!
请您到ITEYE看我的原创:http://cuisuqiang.iteye.com
或支持我的个人博客,地址:http://www.javacui.com
相关推荐
eclipse工程(编译通过,能运行) snmp4j API get,getnext,set,trap,取mib值 实例
本源代码为一个大型程序中的部分,描述了如何使用开源代码SNMP4J的异步模式。
snmp工具文件非常好用的snmp获取工具,get和set功能!
使用Java进行SNMP编程-SNMP4J-代码实例,代码实例实现了GET, GETNEXT, GETBULK, Walk, SET操作; 提供于做服务器监控的朋友;
SNMP4J异步调用示例,实际项目中的源码
smnp get/set方法 target PDU.GETBULK request.add(new VariableBinding(new OID("1.3.6.1.2.1.10000.3.1"))); ResponseEvent responseEvent = snmp.send(request, target); 相应的注释 请参照 注释 修改...
同步和异步请求。 7. 支持像指令回应器一样好的指令发生器。 8. 带有Apache证书模版,开源免费。 9. JAVA 1.4.1或更高版本。 10. 使用LOG4J记录日志。 11. 使用GETBULK实现Row-based矩阵的有效的异步表格获取...
同步和异步请求。 7. 支持像指令回应器一样好的指令发生器。 8. 带有Apache证书模版,开源免费。 9. JAVA 1.4.1或更高版本。 10. 使用LOG4J记录日志。 11. 使用GETBULK实现Row-based矩阵的有效的异步表格获取...
snmp4j get walk 方式获取数据
利用snmp4j实现snmp协议三个版本的get、getnext、set、trap操作的源代码,帮助你快速上手snmp协议的实现
同步和异步请求。 7. 支持像指令回应器一样好的指令发生器。 8. 带有Apache证书模版,开源免费。 9. JAVA 1.4.1或更高版本。 10. 使用LOG4J记录日志。 11. 使用GETBULK实现Row-based矩阵的有效的异步表格获取...
Java使用SNMP4J实现snmp trap接口发送消息_20170808_LK
snmp工具 非常好用的snmp获取工具 具备get和set以及trap功能!
snmp4j 实现snmp trap发送与接收
SNMP V1 V2 V3
最近接触到这个问题,之前也没有了解过snmp,包含了snmp的get以及set方法,大家一起学习学习。
使用snmp4j实现Snmp功能使用snmp4j实现Snmp功能
snmp4j 实现snmpv3get的request集合了v2 v3版本
jar/SNMP4J.jar jar/snmp4jclt-1.2.1.zip jar/snmp.jar 基于java的Oid获取软件.rar Java进行SNMP通信的指南SnmpProgrammingGuideViaJava.doc Java实现snmp的get和walk代码示例.doc snmp4j.chm snmp.chm SnmpMain....