SNMP 使用SNMP4J V2进行TRAP

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

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

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

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

Java代码  收藏代码

  1. package t3;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.UnknownHostException;  
  5. import java.util.Vector;  
  6. import org.snmp4j.CommandResponder;  
  7. import org.snmp4j.CommandResponderEvent;  
  8. import org.snmp4j.MessageDispatcherImpl;  
  9. import org.snmp4j.Snmp;  
  10. import org.snmp4j.TransportMapping;  
  11. import org.snmp4j.mp.MPv1;  
  12. import org.snmp4j.mp.MPv2c;  
  13. import org.snmp4j.mp.MPv3;  
  14. import org.snmp4j.security.SecurityModels;  
  15. import org.snmp4j.security.SecurityProtocols;  
  16. import org.snmp4j.security.USM;  
  17. import org.snmp4j.smi.Address;  
  18. import org.snmp4j.smi.GenericAddress;  
  19. import org.snmp4j.smi.OctetString;  
  20. import org.snmp4j.smi.TcpAddress;  
  21. import org.snmp4j.smi.UdpAddress;  
  22. import org.snmp4j.smi.VariableBinding;  
  23. import org.snmp4j.transport.DefaultTcpTransportMapping;  
  24. import org.snmp4j.transport.DefaultUdpTransportMapping;  
  25. import org.snmp4j.util.MultiThreadedMessageDispatcher;  
  26. import org.snmp4j.util.ThreadPool;  
  27.   
  28. /** 
  29.  * 本类用于监听代理进程的Trap信息 
  30.  */  
  31. public class MultiThreadedTrapReceiver implements CommandResponder {  
  32.       
  33.     public static void main(String[] args) {  
  34.         MultiThreadedTrapReceiver multithreadedtrapreceiver = new MultiThreadedTrapReceiver();  
  35.         multithreadedtrapreceiver.run();  
  36.     }  
  37.   
  38.     private MultiThreadedMessageDispatcher dispatcher;  
  39.     private Snmp snmp = null;  
  40.     private Address listenAddress;  
  41.     private ThreadPool threadPool;  
  42.   
  43.     public MultiThreadedTrapReceiver() {  
  44.     }  
  45.       
  46.     public void run() {  
  47.         try {  
  48.             init();  
  49.             snmp.addCommandResponder(this);  
  50.             System.out.println("--------------->开始监听Trap信息!<---------------");  
  51.         } catch (Exception ex) {  
  52.             ex.printStackTrace();  
  53.         }  
  54.     }  
  55.       
  56.     private void init() throws UnknownHostException, IOException {  
  57.         threadPool = ThreadPool.create("Trap"2);  
  58.         dispatcher = new MultiThreadedMessageDispatcher(threadPool,new MessageDispatcherImpl());  
  59.         listenAddress = GenericAddress.parse(System.getProperty("snmp4j.listenAddress""udp:127.0.0.1/2008")); // 本地IP与监听端口  
  60.         TransportMapping transport;  
  61.         // 对TCP与UDP协议进行处理  
  62.         if (listenAddress instanceof UdpAddress) {  
  63.             transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);  
  64.         } else {  
  65.             transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);  
  66.         }  
  67.         snmp = new Snmp(dispatcher, transport);  
  68.         snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());  
  69.         snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());  
  70.         snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());  
  71.         USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);  
  72.         SecurityModels.getInstance().addSecurityModel(usm);  
  73.         snmp.listen();  
  74.     }  
  75.   
  76.     /** 
  77.      * 实现CommandResponder的processPdu方法, 用于处理传入的请求、PDU等信息 
  78.      * 当接收到trap时,会自动进入这个方法 
  79.      */  
  80.     @SuppressWarnings("unchecked")  
  81.     public void processPdu(CommandResponderEvent respEvnt) {  
  82.         // 解析Response  
  83.         if (respEvnt != null && respEvnt.getPDU() != null) {  
  84.             Vector<VariableBinding> recVBs = respEvnt.getPDU().getVariableBindings();  
  85.             for (int i = 0; i < recVBs.size(); i++) {  
  86.                 VariableBinding recVB = recVBs.elementAt(i);  
  87.                 System.out.println(recVB.getOid() + " : " + recVB.getVariable());  
  88.             }  
  89.         }  
  90.     }  
  91. }  

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

Java代码  收藏代码

  1. public void processPdu(CommandResponderEvent respEvnt)   

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

运行Main方法,控制台提示

Java代码  收藏代码

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

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

使用命令

Java代码  收藏代码

  1. >netstate -an  

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

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

Java代码  收藏代码

  1. package t3;  
  2.   
  3. import java.io.IOException;  
  4. import org.snmp4j.CommunityTarget;  
  5. import org.snmp4j.PDU;  
  6. import org.snmp4j.Snmp;  
  7. import org.snmp4j.TransportMapping;  
  8. import org.snmp4j.mp.SnmpConstants;  
  9. import org.snmp4j.smi.Address;  
  10. import org.snmp4j.smi.GenericAddress;  
  11. import org.snmp4j.smi.OID;  
  12. import org.snmp4j.smi.OctetString;  
  13. import org.snmp4j.smi.VariableBinding;  
  14. import org.snmp4j.transport.DefaultUdpTransportMapping;  
  15.   
  16. /** 
  17.  * 本类用于向管理进程发送Trap信息 
  18.  */  
  19. public class SnmpUtilSendTrap {  
  20.   
  21.     private Snmp snmp = null;  
  22.     private Address targetAddress = null;  
  23.       
  24.     public static void main(String[] args) {  
  25.         try {  
  26.             SnmpUtilSendTrap util = new SnmpUtilSendTrap();  
  27.             util.initComm();  
  28.             util.sendPDU();  
  29.         } catch (IOException e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.     }  
  33.   
  34.     public void initComm() throws IOException {  
  35.         // 设置管理进程的IP和端口  
  36.         targetAddress = GenericAddress.parse("udp:127.0.0.1/2008");  
  37.         TransportMapping transport = new DefaultUdpTransportMapping();  
  38.         snmp = new Snmp(transport);  
  39.         transport.listen();  
  40.     }  
  41.   
  42.     /** 
  43.      * 向管理进程发送Trap报文 
  44.      *  
  45.      * @throws IOException 
  46.      */  
  47.     @SuppressWarnings("unchecked")  
  48.     public void sendPDU() throws IOException {  
  49.         // 设置 target  
  50.         CommunityTarget target = new CommunityTarget();  
  51.         target.setAddress(targetAddress);  
  52.         // 通信不成功时的重试次数  
  53.         target.setRetries(2);  
  54.         // 超时时间  
  55.         target.setTimeout(1000 * 5);  
  56.         // snmp版本  
  57.         target.setVersion(SnmpConstants.version2c);  
  58.         // 创建 PDU  
  59.         PDU pdu = new PDU();  
  60.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.6.0"),new OctetString("aaaa")));  
  61.         pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.2.0"),new OctetString("bbbb")));  
  62.         pdu.setType(PDU.TRAP);  
  63.         // 向Agent发送PDU,并接收Response  
  64.         snmp.send(pdu, target);  
  65.         System.out.println("------------> END<--------------");  
  66.     }     
  67. }  

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

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

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

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

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

1 

1 

分享到:  

 | 申请的群组通过了 Java研发交流 欢迎你

评论

7 楼 cuisuqiang 2014-06-04  

KuhYygy 写道

请问下楼主,如果trap里的包含中文的信息,应该如何解码,准确来讲,应该如何选择字符编码?

String s = new String(((OctetString)recVB.getVariable()).getValue(), "UTF-8");

如上,我看有些写UTF-8,有些写GBK,请问这个应该怎么选择,或者有其它的方法解释出trap里的中文?谢谢~


如果是我们俩之间做通信,咱俩之间肯定知道字符串是什么编码格式的,为什么会出现不知道编码的情况?

6 楼 KuhYygy 2014-06-03  

请问下楼主,如果trap里的包含中文的信息,应该如何解码,准确来讲,应该如何选择字符编码?

String s = new String(((OctetString)recVB.getVariable()).getValue(), "UTF-8");

如上,我看有些写UTF-8,有些写GBK,请问这个应该怎么选择,或者有其它的方法解释出trap里的中文?谢谢~

5 楼 lanqiu17 2014-02-21  

cuisuqiang 写道

lanqiu17 写道

  @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());  
            }  
        }  
    }

楼主,我觉得这里应该交给线程去处理。它占用的是接收trap线程池中的线程,会阻塞trap消息的接收


SNMP4J用的是堵塞线程池处理,既然已经有线程池处理了,为什么再做一层线程处理?除非是担心收到的消息很长时间处理不掉,那增大SNMP线程池就可以了

但当管理设备过多,并且发送trap消息频繁时,增大snmp线程池只是将问题延后了

4 楼 cuisuqiang 2014-02-20  

lanqiu17 写道

  @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());  
            }  
        }  
    }

楼主,我觉得这里应该交给线程去处理。它占用的是接收trap线程池中的线程,会阻塞trap消息的接收


SNMP4J用的是堵塞线程池处理,既然已经有线程池处理了,为什么再做一层线程处理?除非是担心收到的消息很长时间处理不掉,那增大SNMP线程池就可以了

3 楼 lanqiu17 2014-02-20  

  @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());  
            }  
        }  
    }

楼主,我觉得这里应该交给线程去处理。它占用的是接收trap线程池中的线程,会阻塞trap消息的接收

2 楼 lanqiu17 2014-02-20  

哥们, 你也是做网管软件的啊 , 能交流下吗

1 楼 cuisuqiang 2012-06-05  

如果Trap时需要给客户端返回一些信息,可以参考如下代码: 

Java代码  收藏代码

  1. /** 
  2.  * 实现CommandResponder的processPdu方法, 用于处理传入的请求、PDU等信息 
  3.  * 当接收到trap时,会自动进入这个方法 
  4.  */  
  5. @SuppressWarnings("unchecked")  
  6. public void processPdu(CommandResponderEvent respEvnt) {  
  7.     List<VariableBinding> list = new ArrayList<VariableBinding>();  
  8.     // 解析Response  
  9.     if (respEvnt != null && respEvnt.getPDU() != null) {  
  10.         Vector<VariableBinding> recVBs = respEvnt.getPDU().getVariableBindings();  
  11.         for (int i = 0; i < recVBs.size(); i++) {  
  12.             VariableBinding recVB = recVBs.elementAt(i);  
  13.             System.out.println(recVB.getOid() + " : " + recVB.getVariable());  
  14.             Random random = new Random();  
  15.             list.add(new VariableBinding(recVB.getOid(),new Integer32(random.nextInt(1999))));  
  16.         }             
  17.         org.snmp4j.mp.StatusInformation statusInformation = new org.snmp4j.mp.StatusInformation();  
  18.         org.snmp4j.mp.StateReference ref = respEvnt.getStateReference();  
  19.         try {  
  20.             // 创建 PDU  
  21.             PDU vPDU = respEvnt.getPDU();  
  22.             vPDU.setType(PDU.RESPONSE);  
  23.             Random random = new Random();  
  24.             for(int i = 0;i< list.size() ;i++){  
  25.                 VariableBinding vb = list.get(i);  
  26.                 vb.setVariable(new Integer32(random.nextInt(9999)));  
  27.                 vPDU.set(i,vb);  
  28.             }  
  29.             respEvnt.getMessageDispatcher().returnResponsePdu(  
  30.                     respEvnt.getMessageProcessingModel(),  
  31.                     respEvnt.getSecurityModel(),  
  32.                     respEvnt.getSecurityName(),  
  33.                     respEvnt.getSecurityLevel(),   
  34.                     vPDU,  
  35.                     respEvnt.getMaxSizeResponsePDU(),   
  36.                     ref,  
  37.                     statusInformation);  
  38.         } catch (Exception e) {  
  39.             e.printStackTrace();  
  40.         }             
  41.     }  
  42. }  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值