Java使用snmp4j管理设备

Java使用snmp4j管理设备,第1张

Java使用snmp4j管理设备

最近项目中用到了snmp4j包进行设备拓扑,设备性能监控,本文主要讲解一下SNMP,snmp4j包在Java中的使用。

一、SNMP介绍

SNMP是简单网络管理协议,专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及HUBS等)的一种标准协议,它是一种应用层协议。 SNMP 使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长。通过 SNMP 接收随机消息(及事件报告)网络管理系统获知网络出现问题。目前, SNMP 有 3 种: SNMPV1 、 SNMPV2 、 SNMPV3。第 1 版和第 2 版没有太大差距,但 SNMPV2 是增强版本,包含了其它协议 *** 作。与前两种相比, SNMPV3 则包含更多安全和远程配置。

1、基本 *** 作类型

SNMP对外提供了三种用于控制MIB对象的基本 *** 作命令。它们是:Get、Set 和 Trap。Get:管理站读取代理者处对象的值。它是SNMP协议中使用率最高的一个命令,因为该命令是从网络设备中获得管理信息的基本方式。Set:管理站设置代理者处对象的值。Trap: 代理者主动向管理站通报重要事件。Trap 消息可以用来通知管理站线路的故障、连接的终端和恢复、认证失败等消息,管理站可相应的作出处理。

2、snmp消息组成

一条snmp消息由版本识别符、团体名、PDU组成。版本识别符用于说明现在使用的是哪个版本的SNMP协议,确保SNMP代理使用相同的协议,每个SNMP代理都直接抛弃与自己协议版本不同的数据报。团体名是基本的安全机制,用于实现SNMP网络管理员访问SNMP管理代理时的身份验证。PDU (协议数据单元)是SNMP消息中的数据区, 即Snmp通信时报文数据的载体。PDU指明了SNMP的消息类型及其相关参数。

3、MIB(信息管理库)

上文提到了MIB对象,MIB是信息管理库,可以理解成为agent维护的管理对象数据库, MIB数据对象以一种树状分层结构进行组织,这个树状结构中的每个分支都有一个专用的名字和一个数字形式的标识符,可以通过其数字标识符来查找MIB中的数据对象,这个数字标识符号从结构树的顶部(或根部)开始,直到各个叶 子节点(即数据对象)为止。

4、OID

每个管理对象都有自己的OID(Object Identifier),管理对象通过树状结构进行组织,OID由树上的一系列整数组成,也就是从根节点 通向它的路径,整数之间用点( . )分隔开,树的叶子节点才是真正能够被管理的对象。

二、Java实现SNMP

1、搭建环境

首先本地计算机和被管理的设备要开启snmp,然后下载snmp4j包,或者在maven项目pom文件添加依赖。

2、代码实现


import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.*;

public class SNMPUtil {
    private String address="udp:192.160.0.2/161";
    private String username="admin";
    private String authpassword="123";
    private String privpassword="123";
    private Snmp snmp;

    
    public void initSnmp() throws IOException {
        //1、初始化多线程消息转发类
        MessageDispatcher messageDispatcher = new MessageDispatcherImpl();
        //其中要增加三种处理模型。如果snmp初始化使用的是Snmp(TransportMapping transportMapping) ,就不需要增加
        messageDispatcher.addMessageProcessingModel(new MPv1());
        messageDispatcher.addMessageProcessingModel(new MPv2c());
        //当要支持snmpV3版本时,需要配置user
        OctetString localEngineID=new OctetString(MPv3.createLocalEngineID());
        USM usm=new USM(SecurityProtocols.getInstance().addDefaultProtocols(),localEngineID,0);

        OctetString userName= new OctetString(username);
        OctetString authpass= new OctetString(authpassword);
        OctetString privpass= new OctetString(privpassword);
        UsmUser user= new UsmUser(userName,AuthMD5.ID,authpass,PrivDES.ID,privpass);
        usm.addUser(user.getSecurityName(),user);
        messageDispatcher.addMessageProcessingModel(new MPv3(usm));

        TransportMapping transportMapping= new DefaultUdpTransportMapping();
        snmp = new Snmp(messageDispatcher,transportMapping);
        snmp.listen();
    }

    
    public Target createTarget(String oid){
        Target target=null;
        int version=1;
        if(!(version==SnmpConstants.version1||version==SnmpConstants.version2c||version==SnmpConstants.version3)){
            return target;
        }
        if(version==SnmpConstants.version3){
            target = new UserTarget();
            //snmpV3需要设置安全级别和安全名称,其中安全名称是创建snmp指定user设置的new OctetString("SNMPV3")
            target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
            target.setSecurityName(new OctetString(this.username));
        }else {
            target=new CommunityTarget();
            //snmpV1和snmpV2需要指定团体名名称
            target.setSecurityName(new OctetString(this.username));
            if(version==SnmpConstants.version2c){
                target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);
            }
        }
        target.setVersion(version);
        target.setAddress(GenericAddress.parse(this.address));
        target.setRetries(3);
        target.setTimeout(2000);
        return target;
    }
    
    public static void setStringVar(PDU pdu,String oid,String var){
        OID oidStr = new OID();
        oidStr.setValue(oid);
        VariableBinding ipBind = new VariableBinding(oidStr,new OctetString(var));
        pdu.add(ipBind);
    }

    
    public static void setIntVar(PDU pdu,String oid,int var){
        OID oidStr = new OID();
        oidStr.setValue(oid);
        VariableBinding ipBind = new VariableBinding(oidStr,new Integer32(var));
        pdu.add(ipBind);
    }
    
    public static void setGuage(PDU pdu,String oid,long var){
        OID oidStr = new OID();
        oidStr.setValue(oid);
        VariableBinding ipBind = new VariableBinding(oidStr,new Gauge32(var));
        pdu.add(ipBind);
    }
    public static void setIpAddress(PDU pdu,String oid,String var){
        OID oidStr = new OID();
        oidStr.setValue(oid);
        VariableBinding ipBind = new VariableBinding(oidStr,new IpAddress(var));
        pdu.add(ipBind);
    }

    
    private static PDU createPDU(int version,int type,String oid){
        PDU pdu=null;
        if(version==SnmpConstants.version3){
            pdu= new ScopedPDU();
        }else {
            pdu= new PDUv1();
        }
        pdu.setType(type);
        //可以添加多个变量oid
        
        pdu.add(new VariableBinding(new OID(oid)));
        return pdu;
    }

    
    public List snmpGet(String oid){
        try{
            List list= new ArrayList();
            initSnmp();
            Target target = this.createTarget(oid);
            PDU pdu=createPDU(1,PDU.GET,oid);
            ResponseEvent responseEvent = snmp.send(pdu,target);
            PDU response=responseEvent.getResponse();
            if(null==response){
                System.out.println("Timeout.....");
            }else {
                if(response.getErrorStatus()==PDU.noError){
                      Vector vbs= response.getVariableBindings();
                    for (VariableBinding  vb: vbs
                         ) {
                            Map map = new HashMap();
                            map.put("value",vb.getVariable());
                            list.add(map);
                    }
                    return list;
                }else {
                    System.out.println("Error:"+response.getErrorStatusText());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    
    public  boolean setProprety(String oid) {
        boolean bool = false;
        try{
            initSnmp();
            Target target = this.createTarget(oid);
            PDU pdu=createPDU(1,PDU.SET,oid);
            ResponseEvent responseEvent = snmp.send(pdu, target);
            PDU result = responseEvent.getResponse();
            if(result!=null){
                System.out.println("result:"+result.toString());
                if (result.getErrorStatus() == result.noError) {
                    bool = true;
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        return bool;
    }

    public   void snmpwalk(String oid){
        try{
            List list= new ArrayList();
            initSnmp();
            Target target = this.createTarget(oid);
            PDU pdu=createPDU(1,PDU.GETNEXT,oid);
            boolean matched=true;
            while (matched){
                ResponseEvent responseEvent = snmp.send(pdu,target);
                if(responseEvent==null||responseEvent.getResponse()==null){
                    break;
                }
                PDU response=responseEvent.getResponse();
                String nextOid=null;
                Vector vbs= response.getVariableBindings();
                for (int i = 0; i  transport;
                if (listenAddress instanceof UdpAddress) {
                    //必须是本机地址
                    transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
                } else {
                    transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);
                }
                //初始化snmp需要设置messageDispatcher里面的参数和TransportMapping参数
                snmp = new Snmp(dispatcher, transport);
                //消息分发器添加接收的版本信息
                
                snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
                snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
                snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
                //创建具有所提供安全协议支持的USM,//根据本地IP地址和其他四个随机字节创建本地引擎ID
                USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
                SecurityModels.getInstance().addSecurityModel(usm);
                // 添加安全协议,如果没有发过来的消息没有身份认证,可以跳过此段代码
                SecurityProtocols.getInstance().addDefaultProtocols();
                // 创建和添加用户
                OctetString userName1 = new OctetString(username);
                OctetString authPass = new OctetString(authPassword);
                OctetString privPass = new OctetString(privPassword);
                UsmUser usmUser1 = new UsmUser(userName1, AuthMD5.ID, authPass, PrivAES128.ID, privPass);
                //因为接受的Trap可能来自不同的主机,主机的Snmp v3加密认证密码都不一样,所以根据加密的名称,来添加认证信息UsmUser。
                //添加了加密认证信息的便可以接收来自发送端的信息。
                UsmUserEntry userEnty1 = new UsmUserEntry(userName1, usmUser1);
                UsmUserTable userTable = snmp.getUSM().getUserTable();
                // 添加其他用户
                userTable.addUser(userEnty1);
                //开启Snmp监听,可以接收来自Trap端的信息。
                snmp.listen();
                snmp.addCommandResponder(this);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        public void run() {
            try {
                init();
                snmp.addCommandResponder(this);
                System.out.println("开始监听Trap信息!");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        
        @Override
        public void processPdu(CommandResponderEvent respEvnt) {
            // 解析Response
            System.out.println("trap接受到告警消息,开始对消息进行处理");
            try {
                if (respEvnt != null && respEvnt.getPDU() != null) {
                    PDU pdu=respEvnt.getPDU();
                    Vector vbs= pdu.getVariableBindings();
                    for (int i = 0; i  

实际SNMP报文类型还有getBulk,getNext等类型,有兴趣的小伙伴可以自己尝试一下。还有一款MIB Browser(MIB浏览器)是SNMP开发中必备一种工具,有时间再讲一下它的安装和使用。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/3993112.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-10-21
下一篇 2022-10-21

发表评论

登录后才能评论

评论列表(0条)

保存