SNMP协议学习记录(二)

继续来看SNMP,昨天搭了一个测试环境,收到了一票不知道什么含义的数据。

 

深入了解后,发现这跟一个叫做MIB库的东西有关,这个MIB库是一个非标准的库,每个厂家都有自己的MIB库,据说甚至每个厂家的不同产品可能都不同,学一步做一步,先不管mib库,我先来用java实现一个snmp trap的信息接收demo。

我使用的snmp4j一个开源的工具类

下载地址:https://download.csdn.net/download/formatwindowsxp/10607172

另外这是一个anmp4j的api:https://download.csdn.net/download/formatwindowsxp/10607192

package LOGSYSService_Services.ReceiveServicePack;

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.PDU;
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;


/**
 * @author Song
 * snmp协议的监听模块,用于监听snmp客户端发来的信息.
 * 使用snmp4j实现snmp消息监听,
 * snmp4j 版本 2.6.2
 * snmp trap 默认端口162
 * 2018年08月14日 建立对象
 **/
public class ReceiveService_snmp implements CommandResponder//使用snmp4j需要实现一个接口
{
    
	public static void main(String[] args) 
	{
		System.out.println("v1="+MPv1.ID);
		System.out.println("v2="+MPv2c.ID);
		System.out.println("v3="+MPv3.ID);
		ReceiveService_snmp snmp_receive = new ReceiveService_snmp();  
		snmp_receive.run(); //开始监听
	}
	//#region 启动程序
	 public void run() 
	 {  
	        try
	        {  
	        	startListen();  
	            snmp.addCommandResponder(this);  
	            System.out.println("开始监听Trap信息!");  
	        }
	        catch (Exception ex)
	        {  
	            ex.printStackTrace();  
	        }  
	 }
	 //#endregion
    
    //#region 启动监听
    private static Snmp snmp = null;  
    private static Address listenAddress;  
	private static void startListen()
	{
		try
		{
			ThreadPool threadPool= ThreadPool.create("Trap", 2);//启动一个线程池,设置最高两个线程
			MultiThreadedMessageDispatcher dispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());  
		    listenAddress = (Address) GenericAddress.parse("udp:0.0.0.0/162"); //监听所有ip的162端口   tcp:0.0.0.0/162
		    TransportMapping transport = null;  
		    // 对TCP与UDP协议进行处理
		    try 
		    {
		    	if (listenAddress instanceof UdpAddress) 
				{
					System.out.println("使用UDP协议");
					transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);  
				} 
				else
				{
					System.out.println("使用TCP协议");
					transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);  
				}
			} 
		    catch (Exception e)
		    {
		    	System.out.println("接收地址绑定失败,端口162可能被占用,错误信息:"+e.getMessage());
		    	System.exit(0);//绑定失败,停止当前进程
			}		  
			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();  //开始监听
		}
		catch (Exception e)
		{
			System.out.println("启动监听时触发catch异常:"+e.getMessage());
		}
    }
	//#endregion
	
	 //#region processPdu接口具体的实现
    /**
     *  processPdu接口具体的实现
     *  在接收到snmp信息时,会触发这个方法
    **/
    public void processPdu(CommandResponderEvent respEvnt)
    {  
        if (respEvnt != null && respEvnt.getPDU() != null)
        {
            Vector recVBs = (Vector) respEvnt.getPDU().getVariableBindings();//这里提示我类型转换错误,我必须要进行一次强转
            System.out.println("=======================消息内容=======================");
            System.out.println("数据来源:"+respEvnt.getPeerAddress());
            System.out.println("团体名:"+new String(respEvnt.getSecurityName()));//团体名在v1 v2c下可以用来做认证
            String snmpVer = respEvnt.getMessageProcessingModel()==0?
            							"v1":respEvnt.getMessageProcessingModel()==1?
            							"v2c":respEvnt.getMessageProcessingModel()==3?
            							"v3":"其他版本";//其实这里还有一个v2u版本,但网上很少提及不知道是不是应用较少?
            System.out.println("trap版本:"+snmpVer);
            System.out.println(respEvnt.toString());//输出一下整条信息
            for (int i = 0; i < recVBs.size(); i++)
            {  
               VariableBinding recVB = recVBs.elementAt(i);
                System.out.println("oid:"+recVB.getOid());
                System.out.println("variable:"+recVB.getVariable());
            }  
            System.out.println("=======================输出结束=======================");
        }  
    }
    //#endregion
}

代码功底有限,见谅,见谅,实现了一个服务器端,尝试一下接收情况,在之前的CentOS的的中执行一下测试命令。

snmp v1版本测试命令

snmptrap -v1 -c public 10.0.0.188 1.3.6.1.4.1.1 10.10.12.219 2 3 1000 1.3.6.1.9.9.44.1.2.1 i 12 1.3.4.1.2.3.1 s test_snmptrap

snmp v2c版本测试命令

snmptrap -v 2c -c public 10.0.0.188“aaa”1.3.6.1.4.1.2345 SNMPv2-MIB :: sysLocation.0 s“just here”

snmp v3版本测试命令

关于v3版本,在安全性上有提高,需要配置认证相关的参数,这里我先搞定1 2版本,后头再来配置这个。

 

运行命令后,服务端顺利接收到了消息。

SNMP协议学习记录(二)_第1张图片

       消息接收到了,搜索了一下MIB库的相关资料,我是这么想的,MIB库类似一个字典,通过SNMP收到的OID,可以检索到OID对应的内容。按我现在对SNMP的理解,我应该是可以用这几个OID可以确定信息是哪个模块触发的以及事件的详细信息,网上资料比较少,我也是一头雾水,我觉得我现在有两个模式,1。获取设备上的MIB库,然后通过OID比对出对应的信息0.2。使用获取的OID通过SNMP反查得到想要的信息。哪种方式跟符合实际运行情况,我现在也不知道,下面我需要验证一下....

 

你可能感兴趣的:(工作)