java手写一个snmpUtil工具类

最近在公司做网管系统,时常要用到snmp协议去获取设备的性能。公司的snmpUtil类不知道是哪个大佬封装的,从创建snmp协议到创建PDU以至于具体的方法,都在与一个实体类进行绑定。我在使用的过程中,由于业务的需要,不需要那个实体类,因此,越看越不顺眼。在csdn上搜了一下,网上的一些大佬写的,感觉还是可扩展性我还是不太满意。由于业务的需要,有时候要遍历oid以及它的所有子节点,有时候需要获取单个oid对应的值,有时候是根据oid数组获取一个对应的表。因此,我越来越渴望有一个可扩展的snmpUtil工具类。于是乎,我花费了一些时间,研究了一下,最终抽象出了一些snmp工具类。

第一步:先导入maven包

  <dependency>
            <groupId>org.snmp4j</groupId>
            <artifactId>snmp4j</artifactId>
            <version>2.5.8</version>
        </dependency>

第二步:写一个工具类

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModel;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;
import java.util.*;

/**
 * @author XPAN
 * @description: TODO
 * @date 2022/9/26 17:37
 */
public class mySnmpUtil3 {

    private static final Logger logger = LogManager.getLogger(mySnmpUtil3.class);
    private static Snmp snmp   = null;
    private CommunityTarget target;

    //传入要查询的主机ip
    private String hostIp;
    //传入要查询的端口号
    private String hostPort;
    //传入要查询的团体名
    private String community ;
    //接收要查询的oids
    private String oid;

    public String getHostIp() {
        return hostIp;
    }

    public void setHostIp(String hostIp) {
        this.hostIp = hostIp;
    }

    public String getHostPort() {
        return hostPort;
    }

    public void setHostPort(String hostPort) {
        this.hostPort = hostPort;
    }

    public String getCommunity() {
        return community;
    }

    public void setCommunity(String community) {
        this.community = community;
    }

    private String addressGet ;

    //获取设备描述信息
    private String healthOID1 = "1.3.6.1.4.1";
    //设备电源状态
    String healthOID2 = "1.3.6.1.";
    //获取系统温度
    private String healthOID3 = "1.3.6.";

    public mySnmpUtil3(String hostIp,String hostPort, String snmpCommunity,String oid){
        this.setHostIp(hostIp);
        this.setHostPort(hostPort);
        this.setCommunity(snmpCommunity);
        this.oid = oid;
    }

    public void  initSnmp() throws IOException {
        snmp = new Snmp(new DefaultUdpTransportMapping());
        //开启监听
        snmp.listen();
    }

    private  Target createTarget(String oid) {
        //先得到连接的ip和端口号
        this.addressGet = "udp:" + this.getHostIp()+"/"+this.getHostPort();

        Target target = null;
        int version = 1;
        if (!(version == SnmpConstants.version3 || version == SnmpConstants.version2c || version == SnmpConstants.version1)) {
            //log.error("参数version异常");
            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
        {
            //snmpV1和snmpV2需要指定团体名名称
            target = new CommunityTarget();
            ((CommunityTarget) target).setCommunity(new OctetString(this.community));
            if (version == SnmpConstants.version2c) {
                target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);
            }
        }
        target.setVersion(version);
        //必须指定,没有设置就会报错。
        target.setAddress(GenericAddress.parse(this.addressGet));
        target.setRetries(3);
        target.setTimeout(2000);
        return target;
    }

    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
        /*for(String oid:oids){
            pdu.add(new VariableBinding(new OID(oid)));
        }*/
        pdu.add(new VariableBinding(new OID(oid)));
        return pdu;
    }


    /**
     * 这个方法有大用处,有时候我们查出的数据是35:32:30:30:30:30:30:30:30:31:31:37:31:30:32类似于这种格式,然后我们需要把它转为用户可识别的格式,就用它
     * @param octestString
     * @return
     */
    public static String getChinese(String octestString){
        try{

            String[] temps = octestString.split(":");
            byte[] bs = new byte[temps.length];
            for (int j=0;j< temps.length;j++){
                bs[j] = (byte)Integer.parseInt(temps[j],16);
            }
            return new String(bs,"GB2312");
        }catch (Exception e){
            return octestString;
        }
    }
    /**
     * WALK方式请求
     *功能简介:这个方法是getnext,就是遍历该oid下的所有子节点
     */
    public List<Map<String,Object>> snmpWalk() {
        try {

            List<Map<String,Object>> list = new ArrayList<>();

            //1、初始化snmp,并开启监听
            initSnmp();
            //2、创建目标对象
            Target target = createTarget(this.oid);
            //3、创建报文
            PDU pdu = createPDU(2, PDU.GETNEXT, this.oid);
            //4、发送报文,并获取返回结果
            boolean matched = true;
            while (matched) {
                ResponseEvent responseEvent = snmp.send(pdu, target);
                if (responseEvent == null || responseEvent.getResponse() == null) {
                    //LogUtil.info("snmp TimeOut...");
                    break;
                }
                PDU response = responseEvent.getResponse();
                String nextOid = null;
                Vector<? extends VariableBinding> variableBindings = response.getVariableBindings();
                for (int i = 0; i < variableBindings.size(); i++) {

                    VariableBinding variableBinding = variableBindings.elementAt(i);
                    Variable variable = variableBinding.getVariable();
                    nextOid = variableBinding.getOid().toDottedString();
                    //如果不是这个节点下的oid则终止遍历,否则会输出很多,直到整个遍历完。
                    if (!nextOid.startsWith(oid)) {
                        matched = false;
                        break;
                    }
                    Map<String,Object> map = new HashMap();
                    //放入oid以及oid对应获得的值
                    map.put(nextOid,variable);
                    list.add(map);
                }
                if (!matched) {
                    break;
                }
                pdu.clear();
                pdu.add(new VariableBinding(new OID(nextOid)));
            }

            System.out.println("list的大小 = " +list.size());
            return list;

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 功能简介:获取单个节点oid对应的值
     * @throws IOException
     */
    public  void snmpGet( ) throws IOException {


        try {

            //1、初始化snmp,并开启监听
            initSnmp();
            //2、创建目标对象
            Target target = createTarget(this.oid);
            //3、创建报文
            PDU pdu = createPDU(2, PDU.GET, this.oid);
            //4、发送报文,并获取返回结果


            ResponseEvent responseEvent = snmp.send(pdu, target);
            PDU response = responseEvent.getResponse();

            if (response == null) {
                System.out.println("response is null, request time out");
            } else {

                System.out.println("response pdu size is " + response.size());
                for (int i = 0; i < response.size(); i++) {
                    VariableBinding vb = response.get(i);
                    System.out.println(vb.getOid() + " = " + vb.getVariable());
                }

            }
            System.out.println("SNMP GET one OID value finished !");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("SNMP Get Exception:" + e);
        } finally {
            if (snmp != null) {
                try {
                    snmp.close();
                } catch (IOException ex1) {
                    snmp = null;
                }
            }

        }
    }


    //开启监控的main方法。
    public static void main(String[] args) throws IOException {


//        mySnmpUtil3 mySnmpUtil = new mySnmpUtil3("127.0.0.1","161","tuantiming","1.3.6.1.4.1");
//        mySnmpUtil.snmpGet();

//下面这个方法需要有子节点,遍历子节点然后从子节点中拿数据,这里是找华为的实体索引
        mySnmpUtil3 mySnmpUtil = new mySnmpUtil3("127.0.0.1","161","tuantiming","1.3.6.1.2.1.47.1.1.1.1.5");
        List<Map<String, Object>> mapList = mySnmpUtil.snmpWalk();
        Map<String,Integer> result = new HashMap<String,Integer>();
        int flat= 0;
        List<String> resultNeed = new ArrayList<>();
        for (Map<String, Object> map: mapList){
            for (String key:map.keySet()){
                System.out.println("key= "+key +" value= "+ map.get(key));
							//华为
                if (String.valueOf(map.get(key)).equals("9")){
                    String substring = key.substring(25, key.length());
                    resultNeed.add(substring);
                    System.out.println("找到我需要的数据了"+substring+"9");
                    break;
                }

            }
        }
        System.out.println("这是我需要的数据"+resultNeed.get(0));

    }
}

最后,这里的System.out要记得在生产环境换成Log或者给直接去掉。这里先暂时放这两种方法,后面如果业务需要了再更新。

你可能感兴趣的:(解决方法,java,log4j,apache)