java snmp协议 获取数据

最近工作内容涉及到snmp协议相关内容,由于第一次接触,又没有实际的环境测试,写出来的东西自己都不确定能不能用,直到最近有环境后,花了一段时间才搞定。

写下这篇文章,只是给和我之前一样的小白指点一波,让其他人不必再和我一样被折磨一遍,如果大佬看到我哪里有写错,也请指正。

这里首先强调一点,snmp协议,我java代码这边是作为接收者,而提供信息的是机器设备,但我想通过snmp协议获取数据,是由我发起,然后接收返回的参数。

我这边对接的对象是华为交换机,我这边由参考一篇文章,可以根据下面这篇的文章找到对接的机器的型号,再找到oid
http://t.zoukankan.com/zhenwei66-p-10473121.html

然后网上还可以取找一个叫MIB Browser的工具,这个玩意也可以测试snmp

下面是我的java代码,我会逐一解释其中的内容

首先是第一个方法,我是把snmp协议需要的参数全部丢到json文件中了,这个方法是用来处理json文件读取的,然后把读到的信息转成对象,转换的是最下面两个类,再写入snmp配置,两个入参,第一个是json文件中的品牌,第二个是你snmp协议中的请求例如:get,getnext这些。

    private static final Logger logger = LoggerFactory.getLogger(SnmpUtil.class);

    private static final String jsonFile = "Snmp.json";

    private Snmp snmp;

    /**
     * 根据入参,选择json文件内容进行snmp协议发送
     * @author 汪彪
     * @date 2022/7/22 15:23
     * @param name
     * @param pduType
     * @return java.util.List<jee.pluses.com.vo.huawei.Mib>
     */
    public List<Mib> sendSnmp(String name,Integer pduType) throws IOException {

        //读取Snmp.json文件中数据
        String js = null;
        js = readJson(jsonFile);

        //将读取到的字符串实例化成对象
        JSONObject jasonDate = JSONObject.parseObject(js);
        JSONArray pageData = (JSONArray) jasonDate.get("snmp");
        List<SnmpVo> snmpVoList = JSONObject.parseArray(pageData.toString(), SnmpVo.class);
        for (SnmpVo snmpVo : snmpVoList) {
            if (name.equals(snmpVo.getName())){
                return sendSnmp(snmpVo, pduType);
            }
        }
        return null;
    }

这个方法是配置snmp协议属性用的,在这里调用其他方法生成snmp,pdu,target,然后调用send方法就可以收获你想要的值

 /**
     * 获取snmp数据,根据json文件内容
     * @author 汪彪
     * @date 2022/7/22 15:22
     * @param snmpVo
     * @param pduType
     * @return java.util.List<jee.pluses.com.vo.huawei.Mib>
     */
    private List<Mib> sendSnmp(SnmpVo snmpVo,Integer pduType) throws IOException {
        initSnmp(snmpVo);
        PDU pdu = setPDU(snmpVo, pduType);
        Target target = setTarget(snmpVo);
        ResponseEvent responseEvent = snmp.send(pdu, target);
        PDU response = responseEvent.getResponse();
        if (response == null){
            return null;
        }
        List<Mib> mib = snmpVo.getMib();
        for (Mib m : mib) {
            Variable variable = response.getVariable(new OID(m.getOid()));
            m.setValue(String.valueOf(variable));
        }
        return mib;
    }

这里是target的设置,由于我对接的设备是版本为2的,所以版本3行不行,我这里还不确定。但版本1和2 都是一样的,只需要设置地址,和团体名称,加设置版本,基本就可以了

 /**
     * target设置,版本3未测试
     * @author 汪彪
     * @date 2022/7/21 17:12
     * @param snmpVo
     * @return org.snmp4j.Target
     */
    private Target setTarget(SnmpVo snmpVo){
        Address targetAddress = GenericAddress.parse("udp:" + snmpVo.getTargetIp() + "/" + snmpVo.getTargetPort());
        Target target = null;

        //SNMP的不同版本
        if (snmpVo.getVersion() == SnmpConstants.version3) {
            // 添加用户
            OctetString userName = new OctetString(snmpVo.getUserName());
            OctetString userAuthPassword = new OctetString(snmpVo.getUserAuthPassword());
            OctetString userPrivatePassword = new OctetString(snmpVo.getUserPrivPassword());
            UsmUser usmUser = new UsmUser(userName, AuthMD5.ID,userAuthPassword , PrivDES.ID,userPrivatePassword);
            snmp.getUSM().addUser(userName, usmUser);
            target = new UserTarget();
            // 设置安全级别
            ((UserTarget) target).setSecurityLevel(SecurityLevel.AUTH_PRIV);
            ((UserTarget) target).setSecurityName(userName);
            target.setVersion(SnmpConstants.version3);
        } else {
            //设定CommunityTarget
            target = new CommunityTarget();
            if (snmpVo.getVersion() == SnmpConstants.version1) {
                //设置使用的snmp版本
                target.setVersion(SnmpConstants.version1);
            } else {
                //设置使用的snmp版本
                target.setVersion(SnmpConstants.version2c);
            }
            //设置团体名
            ((CommunityTarget) target).setCommunity(new OctetString(snmpVo.getCommunity()));
        }

        //设定地址
        target.setAddress(targetAddress);

        //设置超时重试次数
        target.setRetries(2);

        //设置超时时间
        target.setTimeout(TimeUnit.SECONDS.toMillis(snmpVo.getTimeout()));

        return target;
    }

这里是pdu的设置,这里面的oid非常关键,根据上面的参考文章,找到oid,随便挑一个测试就可以

 /**
     * pdu设置
     * @author 汪彪
     * @date 2022/7/21 16:53
     * @param snmpVo
     * @param pduType
     * @return org.snmp4j.PDU
     */
    private PDU setPDU(SnmpVo snmpVo,Integer pduType){
        PDU pdu = new PDU();
        for (Mib mib : snmpVo.getMib()) {
            pdu.add(new VariableBinding(new OID(mib.getOid())));
        }
        pdu.setType(pduType);
        return pdu;
    }

这边snmp的初始化其实也很简单,没什么需要特别注意的点

 /**
     * snmp初始化
     * @author 汪彪
     * @date 2022/7/21 16:47
     * @param snmpVo
     * @return void
     */
    private void initSnmp(SnmpVo snmpVo) throws IOException {
        snmp = new Snmp(new DefaultUdpTransportMapping());
        if (snmpVo.getVersion() == SnmpConstants.version3) {
            // 设置安全模式
            USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
            SecurityModels.getInstance().addSecurityModel(usm);
        }
        snmp.listen();
    }

这边是我用来读取json文件的方法,json文件我是直接放在了resources文件夹下,大家也可以按目录去放

/**
     * 读取json文件
     * @author 汪彪
     * @date 2022/7/21 16:21
     * @param filePath
     * @return java.lang.String
     */
    public static String readJson(String filePath) throws IOException {
        InputStream inputStream = SnmpUtil.class.getClassLoader().getResourceAsStream(filePath);
        File file = new File(filePath);
        copyInputStreamToFile(inputStream, file);
        if (!file.exists()) {
            logger.error("未找到文件");
        }
        //创建FileInputStream对象
        FileInputStream fileInputStream = new FileInputStream(file);
        //创建InputStreamReader对象
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
        //创建字符输入流
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        //从文件读取字符
        String js = "";
        String line = null;
        while ((line = bufferedReader.readLine()) != null) {
            js += line;
        }
        return js;
    }
    
	/**
     * 复制流
     * @author 汪彪
     * @date 2022/7/22 16:05
     * @param inputStream
     * @param file
     * @return void
     */
    private static void copyInputStreamToFile(InputStream inputStream, File file) throws IOException {
        try (FileOutputStream outputStream = new FileOutputStream(file)) {
            int read;
            byte[] bytes = new byte[1024];
            while ((read = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
        }
    }

这里是协议的配置信息,由json文件转对象时需要用到这个类

package jee.pluses.com.vo.huawei;

import lombok.Data;

import java.util.List;

/**
 * Snmp协议
 *
 * @author 汪彪
 * @date 2022/7/21
 */
@Data
public class SnmpVo {

    /**
     * 品牌名称
     */
    private String name;

    /**
     * 目标ip地址
     */
    private String targetIp;

    /**
     * 目标端口号
     */
    private Short targetPort;

    /**
     * 团体名
     */
    private String community;

    /**
     * 协议版本
     */
    private Integer version;

    /**
     * 超时设置
     */
    private Integer timeout;

    /**
     * 用户名称
     */
    private String userName;

    /**
     *
     */
    private String userAuthPassword;

    /**
     *
     */
    private String userPrivPassword;

    /**
     * 点位信息
     */
    private List<Mib> mib;
}

这里是每个节点的信息类

package jee.pluses.com.vo.huawei;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * 点位信息
 *
 * @author 汪彪
 * @date 2022/7/21
 */
@Data
public class Mib {

    /**
     * 节点名称
     */
    @ApiModelProperty(value="节点名称", name="node", dataType = "String")
    private String node;

    /**
     * OID
     */
    @ApiModelProperty(value="OID", name="oid", dataType = "String")
    private String oid;

    /**
     * 说明
     */
    @ApiModelProperty(value="说明", name="mean", dataType = "String")
    private String mean;

    /**
     * 点位值
     */
    @ApiModelProperty(value="点位值", name="value", dataType = "String")
    private String value;
}

除了最下面两个类,其他方法代码都是在一个类中,以下是导包信息

import jee.pluses.com.common.PageResult;
import jee.pluses.com.service.huawei.HuaWeiService;
import jee.pluses.com.utils.PageResultUtil;
import jee.pluses.com.utils.SnmpUtil;
import jee.pluses.com.utils.huawei.HuaWeiConstants;
import jee.pluses.com.vo.huawei.Mib;
import jee.pluses.com.vo.huawei.PageModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.PDU;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

这是MIB Browser的参数配置,其实和上面我的配置差不多。
Address和Port在target中配置
Community也是在target中配置
Version也是在target中配置
OID则是在PDU中配置
在这里插入图片描述
还有右上角的请求方式,这边是由调用的时候配置,下面就是我调用的时候内容
在这里插入图片描述
下面是我json文件,里面的内容按照自己的需要配置改改就好

{
  "snmp": [
    {
      "name": "华为",
      "targetIp": "127.0.0.1",
      "targetPort": 161,
      "community": "community",
      "version":1,
      "关键注释内容(无其他作用)": "version版本1为0,version版本2为1,version版本3为3",
      "timeout": 5,
      "userName": "",
      "userAuthPassword": "",
      "userPrivPassword": "",
      "mib": [
        {
          "node": "hwEntityCpuUsage",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.1.1.5",
          "mean": "实体CPU使用率,取值范围:2~100。"
        },
        {
          "node": "hwEntityMemUsage",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.1.1.7",
          "mean": "实体内存使用率,取值范围:0~100。"
        },
        {
          "node": "hwEntityMemSize",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.1.1.9",
          "mean": "实体内存容量,单位:Byte。"
        },
        {
          "node": "hwEntityTemperature",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.1.1.11",
          "mean": "实体温度,读取的是温度传感器测量温度的最高值,单位:°C。"
        },
        {
          "node": "hwEntityOpticalTemperature",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.3.1.5",
          "mean": "光模块温度,单位:°C。"
        },
        {
          "node": "hwEntityOpticalVoltage",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.3.1.6",
          "mean": "光模块电压,单位:mV。"
        },
        {
          "node": "hwEntityOpticalBiasCurrent",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.3.1.7",
          "mean": "光模块偏置电流,单位:uA。"
        },
        {
          "node": "hwEntityOpticalRxPower",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.3.1.8",
          "mean": "光模块接收功率,单位:uW,其中uW=(10^(dBM/10))*1000。\nMIB文件中定义此单位是dBm。"
        },
        {
          "node": "hwEntityOpticalTxPower",
          "oid":"1.3.6.1.4.1.2011.5.25.31.1.1.3.1.9",
          "mean": "光模块发送功率,单位:uW。\nMIB文件中定义此单位是dBm。"
        },
        {
          "node": "ifTable",
          "oid":"1.3.6.1.2.1.2.2.1",
          "mean": "接口当前接收和发送报文流量统计信息。"
        },
        {
          "node": "ifOperStatus",
          "oid":"1.3.6.1.2.1.2.2.1.8",
          "mean": "接口当前的状态。"
        },
        {
          "node": "hwIfMonitorInputRate",
          "oid":"1.3.6.1.4.1.2011.5.25.41.1.7.1.1.8",
          "mean": "入方向带宽占用率"
        },
        {
          "node": "hwIfMonitorOutputRate",
          "oid":"1.3.6.1.4.1.2011.5.25.41.1.7.1.1.10",
          "mean": "出方向带宽占用率"
        },
        {
          "node": "dot1dTpFdbAddress",
          "oid":"1.3.6.1.2.1.17.4.3.1.1",
          "mean": "获取设备上所有的MAC Address表项。"
        },
        {
          "node": "hwDynFdbMac",
          "oid":"1.3.6.1.4.1.2011.5.25.42.2.1.3.1.1",
          "mean": "用于管理设备动态MAC地址表。"
        },
        {
          "node": "hwArpDynTable",
          "oid":"1.3.6.1.4.1.2011.5.25.123.1.17.1",
          "mean": "获取设备上的动态ARP表项。"
        },
        {
          "node": "hwArpCfgTable",
          "oid":"1.3.6.1.4.1.2011.5.25.123.1.18.1",
          "mean": "用于设置和查询静态ARP表项。"
        },
        {
          "node": "lldpRemTable",
          "oid":"1.0.8802.1.1.2.1.4.1.1",
          "mean": "记录LLDP远端邻居信息。"
        },
        {
          "node": "dot1dStpPortState",
          "oid":"1.3.6.1.2.1.17.2.15.1.3",
          "mean": "标识端口当前的STP状态:\n•1:disabled\n•2:blocking\n•3:listening\n•4:learning\n•5:forwarding\n•6:broken\n"
        },
        {
          "node": "hwRrppRingState",
          "oid":"1.3.6.1.4.1.2011.5.25.113.2.2.1.4",
          "mean": "环状态。\n当前支持的取值为:\n•1: unknown\n•4: complete\n•5: failed\n•6: linkup\n•7: linkdown\n•8: preforwarding\n•9: linkupnotify\n•10: linkdownnotify\n•11: preforwardnotify\n"
        },
        {
          "node": "vrrpOperState",
          "oid":"1.3.6.1.2.1.68.1.3.1.3",
          "mean": "虚拟路由器的当前状态。此对象定义了四个值:\n•initialize(1):初始化状态。在此状态下,设备不会对VRRP报文做任何处理。\n•backup(2):备用状态。在此状态下,设备接收Master设备发送的VRRP报文,判断Master设备工作是否正常。\n•master(3):主用状态。在此状态下,设备定期发送VRRP通告报文,并转发目的MAC地址是虚拟MAC地址的IP报文。"
        }
      ]
    }
  ]
}

突然发现忘记加导包的内容了
这个是gradle的导入

    //snmp
    implementation 'org.snmp4j:snmp4j:2.8.3'

这个是pom的导入

//snmp
<dependency>
    <groupId>org.snmp4j</groupId>
    <artifactId>snmp4j</artifactId>
    <version>2.8.3</version>
</dependency>

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: Java是一种流行的编程语言,可以通过SNMP协议获取交换机设备的信息。SNMP协议是一种网络管理协议,可以监视网络设备的状态、性能和配置信息。SNMP协议主要由几个组成部分:管理器、被管理设备和MIB(管理信息库)。管理器通过SNMP协议向被管理设备发送请求,被管理设备则通过SNMP协议将其MIB中的信息返回给管理器。 Java提供了一些开源的SNMP库和框架,如SNMP4J和AdventNet SNMP API。这些库提供了SNMP消息的编码和解码、管理器和代理的实现、MIB的管理和解析等功能。 要使用Java获取交换机设备信息,首先需要确定被管理设备的IP地址和端口号,并确保交换机开启SNMP服务。接下来,可以使用SNMP库创建一个管理器,通过SNMP协议向交换机发送请求,请求的内容包括要获取的OID(对象标识符)和请求类型(如GET、GETNEXT、SET等)。OID是唯一标识MIB中管理对象的一组数字,每个OID对应一个特定的数据项,如端口速率、流量等等。管理器发送请求后,交换机则返回相应的MIB数据,管理器可根据需要对这些数据进行解析和处理。 Java通过SNMP协议获取交换机设备信息,可为网络管理员提供更全面、准确、及时的监视和管理工具,有助于提高网络的可靠性和性能。 ### 回答2: Java通过SNMP协议获取交换机设备信息已经成为网络管理和监控领域中非常重要的一项技术。SNMP协议是一种管理网络设备的标准协议,它使用简单而有效的方式来管理网络设备,确保网络设备处于正常运行状态,以便及时发现和纠正可能发生的问题。 Java通过SNMP协议获取交换机设备信息需要使用到Java SNMP库或者第三方的SNMP库,其原理是通过发送SNMP请求来获取相应的数据。交换机设备通常会提供SNMP Agent,Java通过SNMP Agent来实现与交换机设备通信,并获取交换机设备的相关配置信息,如端口状态、MAC地址、 VLAN信息、链路聚合、流量统计、温度信息等。 Java程序通过SNMP协议获取交换机设备信息的实现过程比较复杂,需要先了解SNMP协议的基本原理以及交换机SNMP Agent的工作原理。同时需要了解交换机设备的厂商提供的SNMP OID(对象标识符)和MIB(管理信息库)信息,因为OID和MIB信息是SNMP Agent对外提供的数据接口,Java通过SNMP协议来获取OID和MIB信息的值,从而得知交换机设备的详细信息。 总的来说,Java通过SNMP协议获取交换机设备信息是一种有效的方式,可以提供实时的设备状态信息以及设备故障报警等功能,有助于管理员及时发现和解决网络问题。但是需要注意的是,在实际应用中需要做好网络设备的安全配置,确保只有授权的Java程序可以访问交换机设备的SNMP Agent接口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值