如何使用 snmp4j-2.7.0 在 snmpv3 中获取系统信息

how get system info in snmpv3 using snmp4j-2.7.0

我正在尝试创建一个小应用程序来管理 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

Why am I always getting a time-out (response == null) when sending a request?

Probably you have forgotten to call the listen() method of the TransportMapping (once) or the Snmp class before sending the request.

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

所以在我绞尽脑汁一整天后,答案附在任何需要知道如何将 SNMPV3 与 SNMP4J 结合使用的人身上。

让我们从正常请求开始。 好吧,问题是我将 PDU 与 GETBULK 一起使用,但我没有设置最大重复次数,所以默认值为 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 的全部要点。 所以问题是我将以秒为单位的超时设置为 30 而不是毫秒作为 30000 愚蠢错误。 但后来我得到了更大的错误 "Agent did not return variable bindings in lexicographic order"。 修复它的墙我使用:

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); 
}