- All Implemented Interfaces:
- java.util.EventListener, CommandResponder, Session
snmp類是SNMP4J的核心,它提供了發送和接收SNMP PDUs的方法,所有的SNMP PDU 類型都可以採用同步或者異步的方式被髮送。
Snmp採用獨立的傳輸協議,通過TransportMapping
接口調用addTransportMapping(TransportMapping transportMapping)
方法或者採用默認的構造函數來實現傳輸映射,以此來實現信息的傳輸。
下面的代碼片段是採用UDP傳輸方式來實現一個SNMPv3的SNMP session :
- Address targetAddress = GenericAddress.parse("udp:127.0.0.1/161");
- TransportMapping transport = new DefaultUdpTransportMapping();
- snmp = new Snmp(transport);
- USM usm = new USM(SecurityProtocols.getInstance(),
- new OctetString(MPv3.createLocalEngineID()), 0);
- SecurityModels.getInstance().addSecurityModel(usm);
- transport.listen();
- // add user to the USM
- snmp.getUSM().addUser(new OctetString("MD5DES"),
- new UsmUser(new OctetString("MD5DES"),
- AuthMD5.ID,
- new OctetString("MD5DESUserAuthPassword"),
- PrivDES.ID,
- new OctetString("MD5DESUserPrivPassword")));
- // create the target
- UserTarget target = new UserTarget();
- target.setAddress(targetAddress);
- target.setRetries(1);
- target.setTimeout(5000);
- target.setVersion(SnmpConstants.version3);
- target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
- target.setSecurityName(new OctetString("MD5DES"));
- // create the PDU
- PDU pdu = new ScopedPDU();
- pdu.add(new VariableBinding(new OID("1.3.6")));
- pdu.setType(PDU.GETNEXT);
- // send the PDU
- ResponseEvent response = snmp.send(pdu, target);
- // extract the response PDU (could be null if timed out)
- PDU responsePDU = response.getResponse();
- // extract the address used by the agent to send the response:
- Address peerAddress = response.getPeerAddress();
- An asynchronous SNMPv1 request is sent by the following code:
- // setting up target
- CommunityTarget target = new CommunityTarget();
- target.setCommunity(new OctetString("public"));
- target.setAddress(targetAddress);
- target.setRetries(2);
- target.setTimeout(1500);
- target.setVersion(SnmpConstants.version1);
- // creating PDU
- PDU pdu = new PDU();
- pdu.add(new VariableBinding(new OID(new int[] {1,3,6,1,2,1,1,1})));
- pdu.add(new VariableBinding(new OID(new int[] {1,3,6,1,2,1,1,2})));
- pdu.setType(PDU.GETNEXT);
- // sending request
- 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);
- System.out.println("Received response PDU is: "+event.getResponse());
- }
- };
- snmp.sendPDU(pdu, target, null, listener);
- //Traps (notifications) and other SNMP PDUs can be received by adding the folling code to the first code snippet above:
- CommandResponder trapPrinter = new CommandResponder() {
- public synchronized void processPdu(CommandResponderEvent e) {
- PDU command = e.getPDU();
- if (command != null) {
- System.out.println(command.toString());
- }
- }
- };
- snmp.addCommandResponder(trapPrinter);
- Version:
- 1.8
- Author:
- Frank Fock
- translate:avery_leo
Snmp類提供了一套有關Snmp的功能接口。具體來講,就是發送、接受、創建Snmp消息。
一個Snmp對象是一個Session,而在Snmp4j中,一個Session可以同多個遠程設備通信。
(1) Snmp、Target、PDU三者的關係
Target代表遠程設備或者遠程實體、PDU代表管理端同Target通信的數據,Snmp就代表管理者管理功能(其實就是數據的收發)的具體執行者。
打個比方:Target就是你遠方的戀人,PDU就是你們之間傳遞的情書、而Snmp就是負責幫你寄信收信的郵差。
(2)Snmp收發數據的兩種方式
Snmp可以同步、也可異步收發數據。詳細見代碼示例說明。
(3)Snmp與傳輸層協議
Snmp可以定製傳輸層協議,一般選擇udp,也可以選擇tcp。詳細見代碼示例說明。
(4)Snmp與Usm
創建Snmp用來發送Snmpv3版本的消息時候,一般還要創建USM,將它添加至安全模型管理器(SecriryModels)中,同時還需要向Usm中添加相應的USM用戶(UsmUser)。詳細見代碼示例說明。
代碼示例:(摘自Snmp4j的API文檔)
(1)創建Snmp
1)使用UDP傳輸協議
TransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
2)使用TCP傳輸協議
TransportMapping transport = new DefaultTcpTransportMapping();
snmp = new Snmp(transport);
3)創建用於Snmpv3的Snmp
// 創建Snmp
TransportMapping transport =
new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transport);
if (version == SnmpConstants.version3) {
byte[] localEngineID =
((MPv3)snmp.getMessageProcessingModel(MessageProcessingModel.MPv3)).createLocalEngineID();
// 創建USM
USM usm = new USM(SecurityProtocols.getInstance(),
new OctetString(localEngineID), 0);
// 將USM添加至安全模式管理器中
// 安全模型管理器採用了單例模式,它內部可以維護爲3個安全模型,分別對應Snmp三個版本
SecurityModels.getInstance().addSecurityModel(usm);
snmp.setLocalEngine(localEngineID, 0, 0);
// 添加用戶
snmp.getUSM().addUser(securityName,new UsmUser(securityName,authProtocol,
authPassphrase,privProtocol,privPassphrase));
}
(2)同步收發消息
import org.snmp4j.*;
...
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
...
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());
}
(3)異步收發消息
import org.snmp4j.*;
import org.snmp4j.event.*;
...
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
...
// 增加監聽器
ResponseListener listener = new ResponseListener() {
public void onResponse(ResponseEvent event) {
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);
...
(4)實現trap
實現trap需要三步:
1)創建Snmp;
2)對於listen()使處於網絡監聽(實際上是同於網絡編程中的Socket監聽);
3)實現CommandResponder
接口的監聽器,並且調用Snmp.addCommandResponder(CommandResponder)
註冊監聽器。
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);
transport.listen();
...
// 實現CommandResponder接口
public synchronized void processPdu(CommandResponderEvent e) {
PDU command = e.getPdu();
if (command != null) {
...
}
}
總結
Snmp內含了一個消息分發器,消息分發器中內含了處理網絡的線程,在使用完後最好調用close(),將其資源迴歸處理。
掌握了上面所說的三個概念,基本上可以使用Snmp4j編寫Snmp的程序了。
有關Snmp4j編程最好也最詳細的資料:API文檔和源代碼。關於使用Snmp4j編寫Snmp程序的例子,多線程的例子可以參看源代碼中:org.snmp4j.test包下的MultiThreadedTrapReceiver.java,完整的例子可以參看 org.snmp4j.tools.console包下的SnmpRequest(一個命令行的Snmp管理器)。
不過,要想快速和深入掌握Snmp編程,最好的辦法一定是先弄懂Snmp協議,這方面的資料最權威的就是RFC協議了。