欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SNMP 使用SNMP4J V2进行TRAP

程序员文章站 2022-04-13 16:57:03
...

SNMP trap(SNMP 陷阱):某种入口,到达该入口会使SNMP被管设备主动通知SNMP管理器,而不是等待SNMP管理器的再次轮询!

 

在网管系统中,被管理设备中的代理可以在任何时候向网络管理工作站报告错误情况,例如预制定阈值越界程度等等。代理并不需要等到管理工作站为获得这些错误情况而轮询他的时候才会报告。这些错误情况就是众所周知的SNMP自陷(trap)!

 

网管系统开放监听端口,始终监听被管设备对于该端口的通信信息。被管设备发生故障会主动向该端口发送故障信息,网管系统收到消息进行告警!

 

首先要模拟工作站对端口进行监听,请看如下程序:

package t3;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Vector;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

/**
 * 本类用于监听代理进程的Trap信息
 */
public class MultiThreadedTrapReceiver implements CommandResponder {
	
	public static void main(String[] args) {
		MultiThreadedTrapReceiver multithreadedtrapreceiver = new MultiThreadedTrapReceiver();
		multithreadedtrapreceiver.run();
	}

	private MultiThreadedMessageDispatcher dispatcher;
	private Snmp snmp = null;
	private Address listenAddress;
	private ThreadPool threadPool;

	public MultiThreadedTrapReceiver() {
	}
	
	public void run() {
		try {
			init();
			snmp.addCommandResponder(this);
			System.out.println("--------------->开始监听Trap信息!<---------------");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	private void init() throws UnknownHostException, IOException {
		threadPool = ThreadPool.create("Trap", 2);
		dispatcher = new MultiThreadedMessageDispatcher(threadPool,new MessageDispatcherImpl());
		listenAddress = GenericAddress.parse(System.getProperty("snmp4j.listenAddress", "udp:127.0.0.1/2008")); // 本地IP与监听端口
		TransportMapping transport;
		// 对TCP与UDP协议进行处理
		if (listenAddress instanceof UdpAddress) {
			transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
		} else {
			transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);
		}
		snmp = new Snmp(dispatcher, transport);
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
		snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
		USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
		SecurityModels.getInstance().addSecurityModel(usm);
		snmp.listen();
	}

	/**
	 * 实现CommandResponder的processPdu方法, 用于处理传入的请求、PDU等信息
	 * 当接收到trap时,会自动进入这个方法
	 */
	@SuppressWarnings("unchecked")
	public void processPdu(CommandResponderEvent respEvnt) {
		// 解析Response
        if (respEvnt != null && respEvnt.getPDU() != null) {
        	Vector<VariableBinding> recVBs = respEvnt.getPDU().getVariableBindings();
           	for (int i = 0; i < recVBs.size(); i++) {
            	VariableBinding recVB = recVBs.elementAt(i);
               	System.out.println(recVB.getOid() + " : " + recVB.getVariable());
      		}
		}
	}
}

 

我们采用的是实现 CommandResponder 接口,该接口有一个方法

public void processPdu(CommandResponderEvent respEvnt) 

 

在该端口接收到信息时会主动调用该方法!

运行Main方法,控制台提示

-------------->开始监听Trap信息!<---------------

 

程序对本机端口 2008 开始监听!

使用命令

>netstate -an

 

发现本机UDP端口已经开始监听!

 

我们再来实现Agent,被管设备向网管系统TRAP信息:

package t3;

import java.io.IOException;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

/**
 * 本类用于向管理进程发送Trap信息
 */
public class SnmpUtilSendTrap {

	private Snmp snmp = null;
	private Address targetAddress = null;
	
	public static void main(String[] args) {
		try {
			SnmpUtilSendTrap util = new SnmpUtilSendTrap();
			util.initComm();
			util.sendPDU();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void initComm() throws IOException {
		// 设置管理进程的IP和端口
		targetAddress = GenericAddress.parse("udp:127.0.0.1/2008");
		TransportMapping transport = new DefaultUdpTransportMapping();
		snmp = new Snmp(transport);
		transport.listen();
	}

	/**
	 * 向管理进程发送Trap报文
	 * 
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public void sendPDU() throws IOException {
		// 设置 target
		CommunityTarget target = new CommunityTarget();
		target.setAddress(targetAddress);
		// 通信不成功时的重试次数
		target.setRetries(2);
		// 超时时间
		target.setTimeout(1000 * 5);
		// snmp版本
		target.setVersion(SnmpConstants.version2c);
		// 创建 PDU
		PDU pdu = new PDU();
		pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.6.0"),new OctetString("aaaa")));
		pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.2.0"),new OctetString("bbbb")));
		pdu.setType(PDU.TRAP);
		// 向Agent发送PDU,并接收Response
		snmp.send(pdu, target);
		System.out.println("------------> END<--------------");
	}	
}

 

使用的SNMP版本应该是 V2,V1的操作与V2 TRAP不同!

运行后控制台打印运行结束!

网管系统模拟端打印收到的OID和OID对应的值信息!

 

请您到ITEYE看我的原创:http://cuisuqiang.iteye.com

或支持我的个人博客,地址:http://www.javacui.com