没事练练翻译,想看的凑合着看吧,原文http://www.snmp4j.org/doc/index.html
org.snmp4j包
提供了创建、发送和接收SNMP消息的类和接口。
org.snmp4j包中的类可以用来创建、发送和接收SNMPv1/v2c/v3消息。一个SNMP消息是由协议头和PDU(协议数据单元)构成。这个包主要包含三组类和接口:
- 用于创建SNMP消息和target的类
- 用于发送(生成命令)SNMP消息的类
- 用于分发(命令响应)SNMP消息的类
下面的UML包图描述了SNMP4J API的核心的包之间的依赖关系。用户通常只用到org.snmp4j包和org.snmp4j.smi包。
下面的UML类图展示了org.snmp4j包中的最重要的类以及类之间的关系(不包含和其他包之间的关系)
SNMP 消息和Targets
为了和远程系统交换SNMP消息,系统必须能被识别,并且为消息交换指定重发和超时策略。SNMP4J通过创建一个用于SNMP协议的Target实例来确定一个远程系统。
- 对于SNMPv1和SNMPv2c,采用表示社团信息的CommunityTarget类来指定Target接口中定义的地址、重发及超时策略信息。
- 对于SNMPv3需要用到UserTarget类。它继承自SecureTarget抽象类,用来提供下述的基于用户的安全模型(USM)的用户信息:security name, security level, security model(例如:USM),authoritative engine ID。
一个SNMP消息由消息的数据包:SNMP协议数据单元(PDU)和消息头构成。简单来说,SNMP4J中消息头由Target实例表示,PDU由以下类表示:
- PDUv1 (SNMPv1)
- PDU (SNMPv2c)
- ScopedPDU (SNMPv3)
因此,为了通过SNMP4J发送一个SNMP消息必须创建一个PDU实例和一个Target实例。
PDU 实例
- SNMPv1/v2c GETNEXT PDU
·
· import org.snmp4j.PDU;
· import org.snmp4j.smi.*;
· ...
· PDU pdu = new PDU();
· pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1"))); // sysDescr
· pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.1"))); // ifNumber
· pdu.setType(PDU.GETNEXT);
· ...
- SNMPv3 GETBULK PDU
·
· import org.snmp4j.ScopedPDU;
· import org.snmp4j.smi.*;
· ...
· ScopedPDU pdu = new ScopedPDU();
· pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.1"))); // ifNumber
· pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.10"))); // ifInOctets
· pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.16"))); // ifOutOctets
· pdu.setType(PDU.GETBULK);
· pdu.setMaxRepetitions(50);
· // Get ifNumber only once
· pdu.setNonRepeaters(1);
· // set context non-default context (default context does not need to be set)
· pdu.setContextName(new OctetString("subSystemContextA"));
· // set non-default context engine ID (to use targets authoritative engine ID
· // use an empty (size == 0) octet string)
· pdu.setContextEngineID(OctetString.fromHexString("80:00:13:70:c0:a8:01:0d"));
· ...
- SNMPv1 TRAP PDU
·
· import org.snmp4j.PDUv1;
· ...
· PDUv1 pdu = new PDUv1();
· pdu.setType(PDU.V1TRAP);
· pdu.setGenericTrap(PDUv1.COLDSTART);
· ...
- SNMPv2c/SNMPv3 INFORM PDU
·
· import org.snmp4j.ScopedPDU;
· ...
· ScopedPDU pdu = new ScopedPDU();
· pdu.setType(PDU.INFORM);
· // sysUpTime
· long sysUpTime = (System.currentTimeMillis() - startTime) / 10;
· pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(sysUpTime)));
· pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, SnmpConstants.linkDown));
· // payload
· pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.1"+downIndex),
· new Integer32(downIndex)));
· ...
Target 实例
- Community Target
·
· CommunityTarget target = new CommunityTarget();
· target.setCommunity(new OctetString("public"));
· target.setAddress(targetAddress);
· target.setVersion(SnmpConstants.version1);
- User Target
·
· UserTarget target = new UserTarget();
· target.setAddress(targetAddress);
· target.setRetries(1);
· // set timeout to 500 milliseconds -> 2*500ms = 1s total timeout
· target.setTimeout(500);
· target.setVersion(SnmpConstants.version3);
· target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
· target.setSecurityName(new OctetString("MD5DES"));
发送SNMP消息
SNMP4J使用SNMP 会话接口的实例来发送SNMP消息。这个接口的默认实现是Snmp类。
创建一个Snmp类的实例就必须调用它的带有TransportMapping参数的构造函数。transport mapping被SNMP会话用来表示对一个远程系统发送SNMP消息时采用的传输协议,例如用户数据报协议(UDP)。
一个SNMP4J的Snmp实例支持 SNMP v1,v2c和v3(默认)版本。对于SNMP协议的其它版本可以通过子类华Snmp来支持。
利用SNMP4J,可以采用同步(阻塞)和异步方式来发送SNMP消息。Snmp类对于同步和异步请求没有采用一个内部线程来处理响应信息,而是采用transport mapping的接收线程来处理响应信息。
通过调用一个实现了ResponseListener接口的类的实例的回调方法来接受异步响应信息。回调方法的执行代表了transport mapping线程接收到了响应包。因此,如果被调用的方法阻塞了,transport mapping的监听端口的同步及异步消息的接收也将被阻塞。其它的transport mapping不会受到影响。通过采用同步消息或在回调方法中解耦来避免阻塞。
发送同步消息的实例
import org.snmp4j.*;
...
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
...
ResponseEvent response = snmp.send(requestPDU, target);
if (response.getResponse() == null) {
// request timed out
...
}
else {
System.out.println("Received response from: "+
response.getPeerAddress());
// dump response PDU
System.out.println(response.getResponse().toString());
}
发送异步消息的实例
import org.snmp4j.*;
import org.snmp4j.event.*;
...
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
...
ResponseListener listener = new ResponseListener() {
public void onResponse(ResponseEvent event) {
// Always cancel async request when response has been received
// otherwise a memory leak is created! Not canceling a request
// immediately can be useful when sending a request to a broadcast
// address.
((Snmp)event.getSource()).cancel(event.getRequest(), this);
PDU response = event.getResponse();
PDU request = event.getRequest();
if (response == null) {
System.out.println("Request "+request+" timed out");
}
else {
System.out.println("Received response "+response+" on request "+
request);
}
}
};
snmp.sendPDU(request, target, null, listener);
...
接收SNMP消息
SNMP4J通过transport mappings的监听端口来接受SNMP消息。为了能够接收到响应或请求信息,端口必须被设置为监听模式。必须通过调用TransportMapping实例的listen()方法来启动transport mappings的内部监听线程。通过调用TransportMapping实例或者关联的Snmp实例的close()方法来停止这个内部线程并关闭监听端口。
transport mapping以字节流的形式接收到SNMP消息并将消息转发给关联的MessageDispatcher实例。SNMP4J默认采用MessageDispatcherImpl类来解码和分发收到的消息。MessageDispatcher实例在Snmp类内部被创建和使用。
Snmp类处理未完成的请求的响应信息并且转发其它的SNMP消息的PDU给已注册的CommandResponder监听器实例。为了接收SNMP消息必须像下面这样:
- 创建一个TransportMapping并且通过调用TransportMapping.listen()初始化它的监听端口。
- 利用上边的TransportMapping创建一个Snmp实例。
- 实例化一个实现了CommandResponder接口的类,并且通过调用Snmp实例的Snmp.addCommandResponder(CommandResponder)的方法来注册它。
当接收到一个未处理的SNMP消息(一个没有对应的未完成的request的SNMP消息),CommandResponder的processPdu(CommandResponderEvent)方法将被调用,此方法携带了SNMP消息中的由消息处理模型解码的PDU及附加信息。
接收SNMP消息的实例
import org.snmp4j.*;
import org.snmp4j.smi.*;
import org.snmp4j.mp.SnmpConstants;
...
TransportMapping transport =
new DefaultUdpTransportMapping(new UdpAddress("0.0.0.0/161"));
Snmp snmp = new Snmp(transport);
if (version == SnmpConstants.version3) {
byte[] localEngineID =
((MPv3)snmp.getMessageProcessingModel(MessageProcessingModel.MPv3)).createLocalEngineID();
USM usm = new USM(SecurityProtocols.getInstance(),
new OctetString(localEngineID), 0);
SecurityModels.getInstance().addSecurityModel(usm);
snmp.setLocalEngine(localEngineID, 0, 0);
// Add the configured user to the USM
...
}
snmp.addCommandResponder(this);
snmp.listen();
...
public synchronized void processPdu(CommandResponderEvent e) {
PDU command = e.getPdu();
if (command != null) {
...
}
}