SNMP4J

本文介绍如何利用SNMP4J库方便地实现SNMP网络管理系统(NMS)的功能,包括SNMPv1/v2的操作如GET、GETNEXT、GETBULK和SET,以及利用TableUtils类简化SNMPWalk过程。同时展示了如何通过异步方式实现Agent Discovery,对广播地址发送请求并等待Agent响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用SNMP4J可以很方便的实现一个SNMP NMS的功能。
对于SNMPv1/SNMPv2,简单的说,只需要以下几个步骤
1) 创建Snmp对象snmp

2) 创建CommunityTarget对象target,并指定community, version, address, timeout, retry等参数。

3) 创建PDU对象pdu,并指定操作类型(GET/GETNEXT/GETBULK/SET), 添加VariableBinding(也就是待操作的OID),
    如果是GETBULK操作,还可以指定MaxRepetitions和NonRepeaters。
 注意一定要指定MaxRepetitions,默认值是0,那样不会返回任何结果。

4) 调用snmp.send(pdu, target)方法,发送请求请返回结果。

此外,SNMP4J提供了TableUtils类,可以很轻松的实现一个SNMP Walk的功能,比如一次返回一个表格下面的所有MIB值。
TableUtils类还支持指定ower bound index 和 upper bound index, 得到更小范围的结果以提高性能。这一点对于从一个很多行的表中取一部分行的数据来说很重要。

Snmp还支持异步的send方法。

下面的代码实例实现了GET, GETNEXT, GETBULK, Walk, SET操作,
以及一个利用异步send方法实现的agent discovery: 对一个广播地址发送请求,等待agent返回的应答。
如果需要对一个范围内的IP进行扫描,可以稍加改进,反复调用异步send多次发送给不同IP。

[java]  view plain copy
  1. import java.io.IOException;  
  2. import java.util.List;  
  3. import java.util.Vector;  
  4.   
  5. import org.snmp4j.CommunityTarget;  
  6. import org.snmp4j.PDU;  
  7. import org.snmp4j.Snmp;  
  8. import org.snmp4j.event.ResponseEvent;  
  9. import org.snmp4j.event.ResponseListener;  
  10. import org.snmp4j.mp.SnmpConstants;  
  11. import org.snmp4j.smi.OID;  
  12. import org.snmp4j.smi.OctetString;  
  13. import org.snmp4j.smi.UdpAddress;  
  14. import org.snmp4j.smi.VariableBinding;  
  15. import org.snmp4j.transport.DefaultUdpTransportMapping;  
  16. import org.snmp4j.util.DefaultPDUFactory;  
  17. import org.snmp4j.util.TableEvent;  
  18. import org.snmp4j.util.TableUtils;  
  19.   
  20. public class SNMPv2Test {  
  21.     public static void main(String[] args) throws IOException, InterruptedException {  
  22.         Snmp snmp = new Snmp(new DefaultUdpTransportMapping());  
  23.         snmp.listen();  
  24.           
  25.         CommunityTarget target = new CommunityTarget();  
  26.         target.setCommunity(new OctetString("public"));  
  27.         target.setVersion(SnmpConstants.version2c);  
  28.         target.setAddress(new UdpAddress("192.168.0.100/161"));  
  29.         target.setTimeout(3000);    //3s  
  30.         target.setRetries(1);  
  31.                   
  32.         sendRequest(snmp, createGetPdu(), target);  
  33.         sendRequest(snmp, createGetNextPdu(), target);  
  34.         sendRequest(snmp, createGetBulkPdu(), target);  
  35.         snmpWalk(snmp, target);  
  36.           
  37.         target.setCommunity(new OctetString("private"));  
  38.         sendRequest(snmp, createSetPdu(), target);  
  39.           
  40.         CommunityTarget broadcastTarget = new CommunityTarget();  
  41.         broadcastTarget.setCommunity(new OctetString("public"));  
  42.         broadcastTarget.setVersion(SnmpConstants.version2c);  
  43.         broadcastTarget.setAddress(new UdpAddress("192.168.0.255/161"));  
  44.         broadcastTarget.setTimeout(5000);   //5s  
  45.         sendAsyncRequest(snmp, createGetNextPdu(), broadcastTarget);  
  46.         Thread.sleep(6000); //main thread wait 6s for the completion of asynchronous request   
  47.     }  
  48.       
  49.     private static PDU createGetPdu() {  
  50.         PDU pdu = new PDU();  
  51.         pdu.setType(PDU.GET);  
  52.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3.0"))); //sysUpTime  
  53.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"))); //sysName  
  54.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5")));   //expect an no_such_instance error  
  55.         return pdu;  
  56.     }  
  57.       
  58.     private static PDU createGetNextPdu() {  
  59.         PDU pdu = new PDU();  
  60.         pdu.setType(PDU.GETNEXT);  
  61.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3")));   //sysUpTime  
  62.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5")));   //sysName  
  63.   
  64.         return pdu;  
  65.     }  
  66.       
  67.     private static PDU createGetBulkPdu() {  
  68.         PDU pdu = new PDU();  
  69.         pdu.setType(PDU.GETBULK);  
  70.         pdu.setMaxRepetitions(10);  //must set it, default is 0  
  71.         pdu.setNonRepeaters(0);  
  72.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1")));     //system  
  73.         return pdu;  
  74.     }  
  75.       
  76.     private static PDU createSetPdu() {  
  77.         PDU pdu = new PDU();  
  78.         pdu.setType(PDU.SET);  
  79.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0"), new OctetString("sysname"))); //sysName  
  80.         return pdu;  
  81.     }  
  82.       
  83.     private static void sendRequest(Snmp snmp, PDU pdu, CommunityTarget target)  
  84.     throws IOException {  
  85.         ResponseEvent responseEvent = snmp.send(pdu, target);  
  86.         PDU response = responseEvent.getResponse();  
  87.           
  88.         if (response == null) {  
  89.             System.out.println("TimeOut...");  
  90.         } else {  
  91.             if (response.getErrorStatus() == PDU.noError) {  
  92.                 Vector<? extends VariableBinding> vbs = response.getVariableBindings();  
  93.                 for (VariableBinding vb : vbs) {  
  94.                     System.out.println(vb + " ," + vb.getVariable().getSyntaxString());  
  95.                 }  
  96.             } else {  
  97.                 System.out.println("Error:" + response.getErrorStatusText());  
  98.             }  
  99.         }  
  100.     }  
  101.       
  102.     private static void sendAsyncRequest(Snmp snmp, PDU pdu, CommunityTarget target)  
  103.     throws IOException {  
  104.         snmp.send(pdu, target, nullnew ResponseListener(){  
  105.   
  106.             @Override  
  107.             public void onResponse(ResponseEvent event) {  
  108.                 PDU response = event.getResponse();  
  109.                 System.out.println("Got response from " + event.getPeerAddress());  
  110.                 if (response == null) {  
  111.                     System.out.println("TimeOut...");  
  112.                 } else {  
  113.                     if (response.getErrorStatus() == PDU.noError) {  
  114.                         Vector<? extends VariableBinding> vbs = response.getVariableBindings();  
  115.                         for (VariableBinding vb : vbs) {  
  116.                             System.out.println(vb + " ," + vb.getVariable().getSyntaxString());  
  117.                         }  
  118.                     } else {  
  119.                         System.out.println("Error:" + response.getErrorStatusText());  
  120.                     }  
  121.                 }  
  122.             }});  
  123.     }  
  124.       
  125.     private static void snmpWalk(Snmp snmp, CommunityTarget target) {  
  126.         TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GETBULK));//GETNEXT or GETBULK  
  127.         utils.setMaxNumRowsPerPDU(5);   //only for GETBULK, set max-repetitions, default is 10  
  128.         OID[] columnOids = new OID[] {  
  129.                 new OID("1.3.6.1.2.1.1.9.1.2"), //sysORID  
  130.                 new OID("1.3.6.1.2.1.1.9.1.3"), //sysORDescr  
  131.                 new OID("1.3.6.1.2.1.1.9.1.5")  //wrong OID, expect an null in in VariableBinding array  
  132.         };  
  133.         // If not null, all returned rows have an index in a range (lowerBoundIndex, upperBoundIndex]  
  134.         List<TableEvent> l = utils.getTable(target, columnOids, new OID("3"), new OID("10"));  
  135.         for (TableEvent e : l) {  
  136.             System.out.println(e);  
  137.         }  
  138.     }  
  139. }  
### ### SNMP4J 使用指南与常见问题解析 SNMP4J 是一个用于 Java 开发的开源 SNMP 协议库,支持 SNMP v1、v2c 和 v3 版本,广泛用于网络设备的监控与管理。通过 SNMP4J 可以实现 SNMP GET、SET、WALK、TRAP 等操作,适用于构建网络管理系统、设备状态监控平台等场景。 #### SNMP4J 的基本配置方法 在使用 SNMP4J 之前,需要确保 Java 环境已正确配置,并导入 SNMP4J 库文件。可以通过 Maven 依赖或手动添加 JAR 包的方式引入 SNMP4J。以下是一个典型的 Maven 配置: ```xml <dependency> <groupId>org.snmp4j</groupId> <artifactId>snmp4j</artifactId> <version>3.6.0</version> </dependency> ``` 配置 SNMP4J 时,需创建 `Snmp` 实例并绑定到指定的传输协议(如 UDP)。对于 SNMP v3,还需配置用户安全模型(USM)并设置认证和加密参数。例如: ```java TransportMapping<? extends Address> transport = new DefaultUdpTransportMapping(); Snmp snmp = new Snmp(transport); USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); SecurityModels.getInstance().addSecurityModel(usm); ``` 上述代码片段中,创建了基于 UDP 的 SNMP 实例,并初始化了 USM 安全模型,为 SNMP v3 的身份验证和加密通信做好准备[^2]。 #### SNMP4J 的核心操作实现 使用 SNMP4J 实现 SNMP 操作主要包括 GET、SET、WALK 和 TRAP。以下是一个 GET 请求的实现示例: ```java public static void sendGetRequest(String targetAddress, String community, String oid) throws Exception { Address address = GenericAddress.parse("udp:" + targetAddress + "/161"); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(community)); target.setAddress(address); target.setRetries(2); target.setTimeout(1500); target.setVersion(SnmpConstants.version2c); PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid))); pdu.setType(PDU.GET); Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); snmp.listen(); ResponseEvent event = snmp.send(pdu, target); if (event != null && event.getResponse() != null) { System.out.println("Response: " + event.getResponse()); } else { System.out.println("No response"); } snmp.close(); } ``` 该方法通过 SNMP v2c 协议向指定设备发送 GET 请求,获取指定 OID 的值。类似地,WALK 操作可通过循环发送 GET-NEXT 请求实现,TRAP 操作则需要监听 SNMP 陷阱端口(通常为 UDP 162)并解析传入的 PDU 数据。 #### SNMP4J 常见问题排查 在使用 SNMP4J 时,常见的问题包括连接失败、超时、认证失败以及 PDU 解析异常。连接失败通常由目标设备的 SNMP 服务未启动或防火墙限制导致,需检查 SNMP 服务状态及网络可达性。超时问题可能由网络延迟或设备响应慢引起,建议调整 `setTimeout` 和 `setRetries` 参数以增强容错性。 认证失败主要出现在 SNMP v3 的使用中,通常由于用户名、认证协议(如 SHA、MD5)或密钥配置不一致导致。确保 SNMP4J 中的 USM 配置与设备端的 SNMP v3 用户配置完全一致[^2]。 PDU 解析异常可能由 OID 格式错误或设备返回的数据类型不匹配引起。建议在代码中加入日志输出,捕获并打印完整的 PDU 内容以便分析。例如: ```java if (event != null && event.getResponse() != null) { PDU responsePDU = event.getResponse(); for (VariableBinding vb : responsePDU.getVariableBindings()) { System.out.println(vb.getOid() + " = " + vb.getVariable()); } } ``` 上述代码可帮助开发者清晰地查看响应中的 OID 与值,便于调试和数据提取。 ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值