当前位置: 首页 > 工具软件 > SNMP4J > 使用案例 >

用snmp4j开发网管应用(二) -- 使用snmp4j

焦宁
2023-12-01

用snmp4j开发网管应用(二) -- 使用snmp4j

SNMP协议还算简单

其实针对协议的开发我们只要知道协议的内容,然后架起Socket服务器,然后用字符串拼出协议内容格式的字符串,使用Socket进行通信就好了。

针对协议的开源包主要把这些过程封装了。比如SNMP协议。

我们只需要针对PDU对象编程,然后SNMP4j就会把PDU对象转化为SNMP4j协议的格式,进行BER编码,然后传输,最后解码,再翻译为PDU对象。

先看一下SNMP协议要传输的内容:

http://www.cnpaf.net/Class/SNMP/200408/43.html

这个文章中说的很全和好了。接下来就是用SNMP4J协议的jar包来完成各个功能。

http://www.snmp4j.org/html/download.html

在这个网址中下载最新的SNMP4J的jar包,顺便可以把SNMP4J-Agent-2.2-Instrumentation-Guide.pdf 这个文档描述了对Agent进行开发。SNMP4J把开发包分为了两个,一个SNMP4J.jar主要负责get,trap,set,一个是SNMP4J-Agent.jar主要负责作为一个网元被管理。

 

1 首先说一下怎么开发一个Agent.

 需要用到两个配置文件bc和cfg文件,已经上传到bc_cfg.zip中

大概的代码为:

 

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.snmp4j.agent.BaseAgent;
import org.snmp4j.agent.CommandProcessor;
import org.snmp4j.agent.DuplicateRegistrationException;
import org.snmp4j.agent.io.ImportModes;
import org.snmp4j.agent.mo.DefaultMOTable;
import org.snmp4j.agent.mo.MOTableRow;
import org.snmp4j.agent.mo.snmp.RowStatus;
import org.snmp4j.agent.mo.snmp.SnmpCommunityMIB;
import org.snmp4j.agent.mo.snmp.SnmpNotificationMIB;
import org.snmp4j.agent.mo.snmp.SnmpTargetMIB;
import org.snmp4j.agent.mo.snmp.StorageType;
import org.snmp4j.agent.mo.snmp.VacmMIB;
import org.snmp4j.agent.security.MutableVACM;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModel;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;

public class MyAgent extends BaseAgent {
private List<DefaultMOTable> moTables = new ArrayList<DefaultMOTable>();
private String community;

protected MyAgent(File bootCounterFile, File configFile, List&lt;DefaultMOTable&gt; moTables, String community) {
	super(bootCounterFile, configFile, new CommandProcessor(new OctetString(MPv3.createLocalEngineID())));
	this.moTables = moTables;
	this.community = community;
}

@Override
protected void registerManagedObjects() {
	try {
		for (DefaultMOTable table : moTables) {
			server.register(table, null);
		}
	} catch (DuplicateRegistrationException e) {
		e.printStackTrace();
	}
}

public void startUp(){
	try {
		this.init();
	} catch (IOException e) {
		e.printStackTrace();
	}
	this.loadConfig(ImportModes.REPLACE_CREATE);
	this.addShutdownHook();
	this.getServer().addContext(new OctetString(community));
	this.finishInit();
	this.run();
	this.sendColdStartNotification();
}

/**
 * to set community
 */
@Override
protected void addCommunities(SnmpCommunityMIB communityMIB) {
	Variable[] com2sec = new Variable[] {
			new OctetString(community),              		// community name
			new OctetString("cpublic"),              	// security name
			getAgent().getContextEngineID(),        	// local engine ID
			new OctetString(community),              		// default context name
			new OctetString(),                      	// transport tag
			new Integer32(StorageType.nonVolatile), 	// storage type
			new Integer32(RowStatus.active)         	// row status
	};
	MOTableRow row =
		communityMIB.getSnmpCommunityEntry().createRow(
				new OctetString("public2public").toSubIndex(true), com2sec);
	communityMIB.getSnmpCommunityEntry().addRow(row);

}

}


  •       主要的代码是需要继承BaseAgent

  • 需要设置community

  • 需要注册Table,这个注册中的内容将是供给get和walk的内容。

  • 可以从MIB直接构建Agent,可能需要的包为:mibble-mibs是能够独MIB结构的


2. Trap Receiver


import java.io.IOException;
import java.util.logging.Logger;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
import com.prince.snmp.tool.Command;
import com.prince.snmp.tool.util.Configure;
import com.prince.snmp.tool.util.Const;

/**

  • 构建一个多线程的Trap Receiver
  • @author wangzijian

*/
public class SnmpReceiver implements Command{
private final Logger log = Logger.getLogger(SnmpReceiver.class.getName());

@Override
public void startUp() throws IOException {
	log.info("Snmp Trap Receiver Start");
	log.info("listened on " + Configure.getInstance().getUdpTrapIpPort());
	ThreadPool pool = ThreadPool.create(Const.THREAD_POOL_NAME, Const.AGENT_THREAD_NUM);
	MultiThreadedMessageDispatcher dispatcher = new MultiThreadedMessageDispatcher(pool, new MessageDispatcherImpl());
	Address listenAddress = GenericAddress.parse(Configure.getInstance().getUdpTrapIpPort());
	TransportMapping transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
	// 构建SNMP,并且使其开始监听
	Snmp snmp = new Snmp(dispatcher, transport);
    snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
    snmp.listen();
    snmp.addCommandResponder(new CommandResponderImpl());
}

}

 


package com.prince.snmp.tool.receiver;

import java.util.List;
import java.util.logging.Logger;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;

public class CommandResponderImpl implements CommandResponder {
private final Logger log = Logger.getLogger(CommandResponderImpl.class.getName());

@Override
public void processPdu(CommandResponderEvent event) {
	PDU pdu = event.getPDU();
	if(PDU.TRAP == pdu.getType()){
		operate(pdu);
	}else{
		log.info("pdu method is:" + pdu.getType() + " not a trap");
	}
	
}

private void operate(PDU pdu) {
	List&lt;VariableBinding&gt; bindings = pdu.getBindingList(new OID(".1"));
	
	for (VariableBinding binding : bindings) {
		System.out.println(binding.getOid() + "====" + binding.getVariable().toString());
	}
}

}

 



  •  需要一个多线程的服务器MultiThreadedMessageDispatcher

  • 还需要一个处理类 CommandResponderImpl  snmp.addCommandResponder

  • 在处理类中能够得到PDU,这个类不只可以作为Receiver还能够开发为Agent,但是需要自己来写很多逻辑,还有可能用到文件或者内存数据库


3. send trap


     


package com.prince.snmp.tool.trap;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Vector;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import com.prince.snmp.tool.Command;
import com.prince.snmp.tool.trap.dataGenerator.ITrapGenerator;
import com.prince.snmp.tool.util.Configure;

public class TrapSender implements Command{
private Snmp snmp;
private Address targetAddress;
private ITrapGenerator generator;

public TrapSender(ITrapGenerator generator) {
	this.generator = generator;
	targetAddress = GenericAddress.parse(Configure.getInstance().getUdpTrapIpPort());
	TransportMapping&lt;UdpAddress&gt; transport = null;
	try {
		transport = new DefaultUdpTransportMapping();
		snmp = new Snmp(transport);
		transport.listen();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

public void sendTrap(){
	CommunityTarget target = new CommunityTarget();
	target.setAddress(targetAddress);
	target.setRetries(Configure.getInstance().getRetries());
	target.setTimeout(Configure.getInstance().getTimeOut());
	target.setCommunity(new OctetString(Configure.getInstance().getCommunity()));
	target.setVersion(Configure.getInstance().getSnmpVersion());
	
	List&lt;TrapData&gt; datas = generator.generateTrapData();
	
	try {
		for (TrapData trapData : datas) {
			sendPdu(trapData, target);
		}
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	} catch (InvocationTargetException e) {
		e.printStackTrace();
	} catch (NoSuchMethodException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

private void sendPdu(TrapData trapData, CommunityTarget target) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, IOException {
	PDU pdu = MoToPdu.moToPdu(trapData);
	ResponseEvent respEvnt = snmp.send(pdu, target);
	
	// 解析Response  
    if (respEvnt != null &amp;&amp; respEvnt.getResponse() != null) {  
        Vector&lt;VariableBinding&gt; recVBs = (Vector&lt;VariableBinding&gt;) respEvnt.getResponse().getVariableBindings();  
        for (int i = 0; i &lt; recVBs.size(); i++) {  
            VariableBinding recVB = recVBs.elementAt(i);  
            System.out.println(recVB.getOid() + " : " + recVB.getVariable());  
        }  
    }
}

}


  •   trap主要注意必须设置两个VariableBingding


                pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(trap.getSysUpTime())));


 


                pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, new OID(trap.getTrapOid())))


 


4. get


     


	private static void simpleGet() throws IOException {
TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transport);
transport.listen();
	CommunityTarget target = new CommunityTarget(); 
	target.setCommunity(new OctetString("CONV"));
	Address targetAddress = GenericAddress.parse("udp:10.141.43.237/161"); 
	target.setAddress(targetAddress);
	target.setRetries(3);
	target.setTimeout(3000);
	target.setVersion(SnmpConstants.version2c);
	
	PDU pdu = new PDU();  
    pdu.add(new VariableBinding(new OID(".1.3.6.1.4.1.7569.1.2.1.23.3.1")));  
    pdu.setType(PDU.GETBULK);
    pdu.setMaxRepetitions(20);
    pdu.setNonRepeaters(0);
    
    ResponseEvent respEvnt = snmp.send(pdu, target);  
    if (respEvnt != null &amp;&amp; respEvnt.getResponse() != null) {  
           Vector&lt;VariableBinding&gt; recVBs = (Vector&lt;VariableBinding&gt;) respEvnt.getResponse().getVariableBindings();  
           for (int i = 0; i &lt; recVBs.size(); i++) {  
                  VariableBinding recVB = recVBs.elementAt(i);  
                  System.out.println(recVB.getOid() + " : " + recVB.getVariable());  

           }  

    }  
}</code></pre> 
<ul>
 <li>&nbsp; &nbsp; &nbsp;get相对于比较简单,资料也比较多。主要是设定pdu.setType(PDU.GETBULK);</li> 
 <li>利用getnext和一些判断可以实现walk.</li> 
 <li>http://blog.sina.com.cn/s/blog_6cb15f8f0100yx4p.html 这个哥们儿写得非常好</li> 
</ul>
<p>具体的代码没有写,因为下一篇会共享一个小的工具,可以以配置文件为基础来构建Receiver,发送Trap,构建Agent等。</p> 
<p>&nbsp;</p> 
 类似资料: