首页 > 解决方案 > 如何使用 snmp4j-2.7.0 在 snmpv3 中获取系统信息

问题描述

我正在尝试创建小型应用程序来管理 snmp 设备,并且首先我想获取系统信息。

我使用的是 snmp4j 版本 2.7.0、java 1.8,设备使用 snmpv3。首先,我想同步获取数据。我尝试以两种方式做到这一点,但我一直在抽空

这是我的代码

    //Normal request
public class SynchronouslySnmp 
{
    protected String PORT="/161";
    protected String PROTOCOL="udp:";
    protected SnmpData snmpData;
    protected Snmp snmp;

    public SynchronouslySnmp(SnmpData snmpData)
    {
        this.snmpData=snmpData;

    }

    public void start()
    {
        createSNMPsession(); 
        addSnmpUser();
        sendSnmp();
    }


    private void sendSnmp() 
    {
           // send the PDU
        ResponseEvent response;
        try 
        {
            response = snmp.send(getPDU(), getTarget());
            // extract the response PDU (could be null if timed out)
            PDU responsePDU = response.getResponse();
            // extract the address used by the agent to send the response:
            if(responsePDU == null)
            {
                System.out.println("ERROR: table OID [" + SnmpContants.system + "] time out" );  
            }
            else
            {
                Address peerAddress = response.getPeerAddress();
                System.out.println("pdu: "+responsePDU.toString());
                System.out.println("Address: "+peerAddress.toString());
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try 
            {
                snmp.close();
            } catch (IOException e) 
            {
                e.printStackTrace();
            }
        }
    }

    protected void createSNMPsession() 
    {
        TransportMapping<? extends Address> transport;
        try 
        {
            transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
            SecurityModels.getInstance().addSecurityModel(usm);
            transport.listen();
            //snmp.listen();
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }

    protected void addSnmpUser()
    {
        // add user to the USM
        snmp.getUSM().addUser(new OctetString(snmpData.getUsmUser()),
                              new UsmUser(new OctetString(snmpData.getUsmUser()),
                                          snmpData.getAuthProtocol(),
                                          new OctetString(snmpData.getAuthPassword()),
                                          snmpData.getPrivProtocol(),
                                          new OctetString(snmpData.getPrivPassword())));
    }

    protected Target getTarget()
    {
         // create the target
           UserTarget target = new UserTarget();
           Address targetAddress = GenericAddress.parse(PROTOCOL+snmpData.getIpAddress()+PORT);
           target.setAddress(targetAddress);
           target.setRetries(snmpData.getRetryTimes());
           target.setTimeout(snmpData.getTimeout());
           target.setVersion(snmpData.getSnmpVersion());
           target.setSecurityLevel(snmpData.getSecurityLevel());
           target.setSecurityName(new OctetString(snmpData.getUsmUser()));
           return target;
    }

    protected PDU getPDU() 
    {
        // create the PDU
        PDU pdu = new ScopedPDU();
        pdu.add(new VariableBinding(SnmpConstants.system));
        pdu.setType(PDU.GETBULK);
        return pdu;
    }
}

我尝试使用treeUtil,但得到与正常请求相同的错误,以下是我的代码

    public class SynchronouslySnmpUsingTree extends SynchronouslySnmp
{
    private OID tableOid;
    private LinkedHashMap<String, List<VariableBinding>> resultMap;

    public SynchronouslySnmpUsingTree(SnmpData snmpData)
    {
        super(snmpData);
        resultMap = new LinkedHashMap<String, List<VariableBinding>>();
        tableOid=new OID(".1.3.6.1.2.1.1");
        createSNMPsession(); 
        addSnmpUser();
        sendSnmp();
    }

    private void sendSnmp()
    {
        try 
        {
            TreeUtils treeUtils = new TreeUtils(snmp, new PDUFactory()
            {
                @Override
                public PDU createPDU(MessageProcessingModel arg0) {
                    return  getPDU();
                }

                @Override
                public PDU createPDU(Target arg0) {

                    return getPDU();
                }
            });
            List<TreeEvent> events = treeUtils.getSubtree(getTarget(), tableOid);
            if (events == null || events.size() == 0)
            {
                System.out.println("Error: Unable to read table...");
                return;
            }
            for (TreeEvent event : events)
            {
                if (event != null && !event.isError()) 
                {
                    VariableBinding[] varBindings = event.getVariableBindings();
                    if (varBindings != null && varBindings.length != 0)
                    {
                        for (VariableBinding varBinding : varBindings) 
                        {
                            if (varBinding != null)
                            {
                                OID oid = varBinding.getOid();
                                List<VariableBinding> binds = resultMap.get(oid.toString());
                                if( binds == null)
                                {
                                    binds = new ArrayList<VariableBinding>();
                                    resultMap.put(oid.toString(), binds);
                                }
                                binds.add(varBinding);
                            }
                        }
                    }
                }
                else
                {
                    System.out.println("Error: table OID [" + tableOid + "] " + event.getErrorMessage());
                    continue;
                }
            }
        }
        catch(Throwable t)
        {
                System.out.println("Failed operation: getMibTableWithNext");
                t.printStackTrace();
        }
        finally 
        {
            try
            {
                snmp.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}

主功能

public static void main(String[] args){
    SynchronouslySnmp synchronouslySnmp =new SynchronouslySnmp (new SnmpData());
    synchronouslySnmp.start();
    SynchronouslySnmpUsingTree synchronouslySnmpUsingTree = new SynchronouslySnmpUsingTree(new SnmpData());
}

运行程序的结果

Error: table OID [1.3.6.1.2.1.1] time out); <---nurmal
Error: table OID [1.3.6.1.2.1.1] Request time out); <---tree

我看https://www.snmp4j.org/html/faq.html

为什么我在发送请求时总是超时(响应 == null)?

可能您在发送请求之前忘记调用TransportMapping(一次)或Snmp 类的listen() 方法。

但是我在 createSNMPsession() 方法中这样做了,那我做错了什么?谢谢。:)

标签: javasnmpmibsnmp4j

解决方案


因此,在我绞尽脑汁一整天之后,任何需要知道如何将 SNMPV3 与 SNMP4J 一起使用的人都可以得到答案。

让我们从正常的请求开始。问题是我使用带有 GETBULK 的 PDU,但我没有设置最大重复次数,所以默认值为 0,我得到了空的 VBS

修复它只需使用:

protected PDU getPDU() 
{
    // create the PDU
    PDU pdu = new ScopedPDU();
    pdu.add(new VariableBinding(SnmpConstants.system));
    pdu.setType(PDU.GETBULK);
    pdu.setMaxRepetitions(10);//or any number you wish
    return pdu;
}

对于树问题,无需定义最大重复次数,这是 getSubTree 的全部要点。所以问题是我将timeOut in sec设置为30而不是millisec设置为30000愚蠢的错误。但后来我得到更大的错误“代理没有按字典顺序返回变量绑定”。我用墙来修复它:

treeUtils.setIgnoreLexicographicOrder(true);
List<TreeEvent> events = treeUtils.getSubtree(getTarget(), tableOid);
if (events == null || events.size() == 0)
{
    System.out.println("Error: Unable to read table...");
    return;
}
 .
 .
 .
if( binds == null)
{
    binds = new ArrayList<VariableBinding>();
    binds.add(varBinding);
    resultMap.put(oid.toString(), binds); 
}

推荐阅读