snmp4j中主要的类有 Snmp 、PDU、 CommunityTarget 、TransportMapping。下面分别介绍
1、Snmp
Snmp类:该类是SNMP4J中最为核心的类。负责SNMP报文的接受和发送。它提供了发送和接收PDU的方法,所有的PDU类型都可以采用同步或者异步的方式被发送。它有一个无参构造方法和3个重载构造方法。如下:
public Snmp() {
this.pendingRequests = new Hashtable(50);
this.asyncRequests = new Hashtable(50);
this.timeoutModel = new DefaultTimeoutModel();
this.notificationDispatcher = null;
this.reportHandler = new Snmp.ReportProcessor();
this.messageDispatcher = new MessageDispatcherImpl();
}
public Snmp(TransportMapping transportMapping) {
this();
this.initMessageDispatcher();
if (transportMapping != null) {
this.addTransportMapping(transportMapping);
}
}
public Snmp(MessageDispatcher messageDispatcher, TransportMapping transportMapping) {
this.pendingRequests = new Hashtable(50);
this.asyncRequests = new Hashtable(50);
this.timeoutModel = new DefaultTimeoutModel();
this.notificationDispatcher = null;
this.reportHandler = new Snmp.ReportProcessor();
this.messageDispatcher = messageDispatcher;
this.messageDispatcher.addCommandResponder(this);
if (transportMapping != null) {
this.addTransportMapping(transportMapping);
}
}
public Snmp(MessageDispatcher messageDispatcher) {
this.pendingRequests = new Hashtable(50);
this.asyncRequests = new Hashtable(50);
this.timeoutModel = new DefaultTimeoutModel();
this.notificationDispatcher = null;
this.reportHandler = new Snmp.ReportProcessor();
this.messageDispatcher = messageDispatcher;
this.messageDispatcher.addCommandResponder(this);
}
2、PDU类和ScopedPDU类
该类是SNMP报文单元的抽象,其中PDU类适用于SNMPv1和SNMPv2c。ScopedPDU类继承于PDU类,适用于SNMPv3。
3、Target接口和CommunityTarget类以及UserTarget类
对应于SNMP代理的地址信息,包括IP地址和端口号(161)。其中Target接口适用于SNMPv1和SNMPv2c。CommunityTarget类实现了Target接口,用于SNMPv1和SNMPv2c这两个版本,UserTarget类实现了Target接口,适用于SNMPv3。
4、TransportMapping接口
该接口代表了SNMP4J所使用的传输层协议。这也是SNMP4J一大特色的地方。按照RFC的规定,SNMP是只使用UDP作为传输层协议的。而SNMP4J支持管理端和代理端使用UDP或者TCP进行传输。该接口有两个子接口。
Snmp、Target、PDU三者的关系
Target代表远程设备或者远程实体、PDU代表管理端同Target通信的数据,Snmp就代表管理者管理功能(其实就是数据的收发)的具体执行者。
打个比方:Target就是你远方的恋人,PDU就是你们之间传递的情书、而Snmp就是负责帮你寄信收信的邮差。
2、SNMP4J的两种消息发送模式
SNMP4J支持两种消息发送模式:同步发送模式和异步发送模式。
同步发送模式也称阻塞模式。当管理端发送出一条消息之后,线程会被阻塞,直到收到对方的回应或者时间超时。同步发送模式编程较为简单,但是不适用于发送广播消息。
异步发送模式也称非阻塞模式。当程序发送一条消息之后,线程将会继续执行,当收到消息的回应的时候,程序会对消息作出相应的处理。要实现异步发送模式,需要实例化一个实现了ResponseListener接口的类的对象。ResponseListener接口中有一个名为onResponse的函数。这是一个回调函数,当程序收到响应的时候,会自动调用该函数。由该函数完成对响应的处理。
3、使用snmp4j步骤
(1)初始化
-
明确SNMP在传输层所使用的协议 一般情况下,我们都使用使用UDP协议作为SNMP的传输层协议,所以我们需要实例化的是一个DefaultUdpTransportMapping接口对象;
-
实例化一个snmp对象 在此过程中,我们需要将1中实例化的DefaultUdpTransportMapping接口的对象作为参数,穿snmp类的构造函数中。另外,如果实现的SNMPv3协议,我们还需要设置安全机制,添加安全用户等等;
-
监听snmp消息 在此,我们可以调用刚刚实例化的DefaultUdpTransportMapping的接口对象的listen方法,让程序监听snmp消息;
(2)构造发送目标
如果实现的是SNMPv2c或者说SNMPv1,需要实例化一个CommunityTarget对象。如果实现的是SNMPv3程序,则需要实例化一个UserTarget对象。
之后,我们还需要对实例化的对象做一些设置。如果是CommunityTarget的对象,则需要设置使用的Snmp版本,重传时间和等待时延。如果是UserTarget对象,我们不仅需要设置版本、重传时间、等待时延,还需要设置安全级别和安全名称。
(3)构造发送报文
如果发送的是SNMPv2c或者说SNMPv1的报文,我们需要实例化一个PDU类的对象。如果发送的是SNMPv3的报文,我们则需要实例化一个ScopedPDU类的对象。之后,我们还需要生成一个OID对象,其中包含了我们所需要获取的SNMP对象在MIB库中的ID。然后我们需要将OID和之前生成的PDU对象或者是ScopedPDU对象绑定,并且设置PDU的报文类型(五种SNMP报文类型之一)。
(4)构造响应监听对象(异步模式)
当使用异步模式的时候,我们需要实例化一个实现了ResponseListener接口的对象,作为响应消息的监听对象。在构造该对象的过程中,我们需要重写ResponseListener的OnResponse函数,该函数是一个回调函数,用来处理程序收到响应后的一些操作。
(5)发送消息
当所有上述操作都设置完毕之后,就可以发送消息了。同步模式和异步模式发送消息调用的函数名字均为send,但是两个函数所需参数不一样。同步模式的参数仅为2和3中构造的目标对象和报文对象,而异步模式还需要上述的构造的监听对象。
同步模式发送消息后便等待响应的到达,到达之后会返回一个ResponseEvent对象,该对象中包含了响应的相应信息。
异步模式发送消息之后便会继续执行,当收到响应消息时便会调用监听对象的OnResponse函数。该函数中的语句便是我们对响应的处理。
具体代码如下:
package demo1;
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.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.io.IOException;
public class SNMPdemo {
public static void main(String[] args) {
Address address = GenericAddress.parse("udp:192.168.103.177/161");
CommunityTarget communityTarget = new CommunityTarget();
communityTarget.setCommunity(new OctetString("public"));
communityTarget.setAddress(address);
communityTarget.setTimeout(10000);
communityTarget.setVersion(SnmpConstants.version2c);
PDU pduSet = createSetPDU();
PDU pduGet = createGetPDU();
sendPDU(pduSet, communityTarget);
sendPDU(pduGet, communityTarget);
}
//1.3.6.1.2.1.1.5.0
public static PDU createSetPDU(){
PDU pdu = new PDU();
pdu.setType(PDU.SET);
VariableBinding vb = new VariableBinding(new OID("1.3.6.1.2.1.1.1.0"), new OctetString("testname"));
pdu.add(vb);
return pdu;
}
//
public static PDU createGetPDU(){
PDU pdu = new PDU();
pdu.setType(PDU.GET);
VariableBinding vb = new VariableBinding(new OID("1.3.6.1.2.1.1.1.0"));
pdu.add(vb);
return pdu;
}
//
public static void sendPDU(PDU pdu, CommunityTarget communityTarget){
try {
TransportMapping transportMapping = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transportMapping);
snmp.listen();
ResponseEvent responseEvent = snmp.send(pdu, communityTarget);
PDU pduResponse = responseEvent.getResponse();
if(null != pduResponse){
System.out.println("size = " + pduResponse.size());
for(int i =0;i<pduResponse.size();i++){
VariableBinding variableBinding = pduResponse.get(i);
Variable variable = variableBinding.getVariable();
System.out.println("variable = " + variable);
}
System.out.println("error : " + pduResponse.getErrorStatusText());
}else {
System.out.println("Time out ...");
}
} catch (IOException e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
运行结果:
Time out ...
size = 1
variable = Hardware: Intel64 Family 6 Model 158 Stepping 9 AT/AT COMPATIBLE - Software: Windows Version 6.3 (Build 17134 Multiprocessor Free)
error : Success
Process finished with exit code 0