一、前言
之前有在弄监控服务器这块的工作,今天来整体总结下。因为有些服务器(路由器、交换机等都是基于snmp协议的)必须使用snmp协议去监控采集和接收信息,所以必须去了解snmp相关内容,以及如何在基于java上开发。关于了解snmp相关内容,必看《SNMP简单网络管理协议》这本书里面介绍的很详细,另外推荐这位前辈的博文写的很到位 《snmp学习总结》。关于snmp4j的介绍也可以看看前面这位前辈关于 《snmp学习总结》的最后一篇博文《snmp4j介绍》。当然本篇主要记录如何基于Java如何使用snmp4j去开发实现监控与采集,下面我们直接结合源码以及实例讲解:
二、针对源码进行分析:
1、核心对象SNMP的初始化。
源码中有四种初始化方法及四个构造函数,其实都大同小异:参数少的就必须后续添加,参数多的必须提前初始化。
我们先看看第一个无参构造函数,源码很简单,但是注释很多,所以看源码必须要先看注释。
1 /** 2 * Creates a { @code Snmp} instance that uses a 3 * { @code MessageDispatcherImpl} with no message processing 4 * models and no security protols (by default). You will have to add 5 * those by calling the appropriate methods on 6 * { @link #getMessageDispatcher()}. 7 * <p> 8 * At least one transport mapping has to be added before { @link #listen()} 9 * is called in order to be able to send and receive SNMP messages. 10 * <p> 11 * To initialize a { @code Snmp} instance created with this constructor 12 * follow this sample code: 13 * <pre> 14 * Transport transport = ...; 15 * Snmp snmp = new Snmp(); 16 * SecurityProtocols.getInstance().addDefaultProtocols(); 17 * MessageDispatcher disp = snmp.getMessageDispatcher(); 18 * disp.addMessageProcessingModel(new MPv1()); 19 * disp.addMessageProcessingModel(new MPv2c()); 20 * snmp.addTransportMapping(transport); 21 * OctetString localEngineID = new OctetString( 22 * MPv3.createLocalEngineID()); 23 * // For command generators, you may use the following code to avoid 24 * // engine ID clashes: 25 * // MPv3.createLocalEngineID( 26 * // new OctetString("MyUniqueID"+System.currentTimeMillis()))); 27 * USM usm = new USM(SecurityProtocols.getInstance(), localEngineID, 0); 28 * disp.addMessageProcessingModel(new MPv3(usm)); 29 * snmp.listen(); 30 * </pre> 31 */ 32 public Snmp() { 33 this.messageDispatcher = new MessageDispatcherImpl(); 34 if (SNMP4JSettings.getSnmp4jStatistics() != SNMP4JSettings.Snmp4jStatistics.none) { 35 counterSupport = CounterSupport.getInstance(); 36 } 37 }
从上面注释中可以看出要初始化snmp需要设置messageDispatcher里面的参数和TransportMapping参数,如果没有设置好这个两个参数,发送报文时会报错(见下面案例).所以我们可以直接使用第三个构造函数。
接下来我们来看第二个构造函数Snmp(TransportMapping<? extends Address> transportMapping):
1 /** 2 * Creates a <code>Snmp</code> instance that uses a 3 * <code>MessageDispatcherImpl</code> with all supported message processing 4 * models and the default security protols for dispatching. 5 * <p> 6 * To initialize a <code>Snmp</code> instance created with this constructor 7 * follow this sample code: 8 * <pre> 9 * Transport transport = ...; 10 * Snmp snmp = new Snmp(transport); 11 * OctetString localEngineID = 12 * new OctetString(snmp.getMPv3().getLocalEngineID()); 13 * USM usm = new USM(SecurityProtocols.getInstance(), localEngineID, 0); 14 * SecurityModels.getInstance().addSecurityModel(usm); 15 * snmp.listen(); 16 * </pre> 17 * 18 * @param transportMapping TransportMapping 19 * the initial <code>TransportMapping</code>. You can add more or remove 20 * the same later. 21 */ 22 public Snmp(TransportMapping<? extends Address> transportMapping) { 23 this(); 24 initMessageDispatcher(); 25 if (transportMapping != null) { 26 addTransportMapping(transportMapping); 27 } 28 }
protected final void initMessageDispatcher() { this.messageDispatcher.addCommandResponder(this); this.messageDispatcher.addMessageProcessingModel(new MPv2c()); this.messageDispatcher.addMessageProcessingModel(new MPv1()); this.messageDispatcher.addMessageProcessingModel(new MPv3()); SecurityProtocols.getInstance().addDefaultProtocols(); }
从源码中可以看到它帮我们设置了messageDispatcher里面的参数,只要我们提供TransportMapping参数即可。第四个构造函数Snmp(MessageDispatcher messageDispatcher)其实跟第一个类似同样需要提供两个参数,所以第三个和第四个就列出来了。其中涉及到接口有MessageDispatcher接口、MessageProcessingModel接口,涉及到的类有MPv1、MPv2和MPv3分别对应snmp版本v1、v2c和v3。
/** * @description MessageDispatcher接口定义了处理传入的SNMP消息并将其分派到感兴趣的CommandResponder实例的实例的公共服务。它还提供了一个发送出去的SNMP消息的服务。 */ public interface MessageDispatcher extends Transpor