0

我是 snmp 新手,使用 snmp4j 创建 snmp 代理。我的 java 应用程序需要侦听 snmp 请求并根据传入的 oid 查询 db 并发回响应。我有一个 snmp 代理的 src 代码。但是agent是如何根据传入的oid查询db的呢?我是否需要将数据库中的所有 oid 注册为代理中的托管对象,以便代理可以在请求到达时进行查找?或者换句话说,我如何从代理指向我的数据存储/数据库?

这是我正在使用的代码。

http://shivasoft.in/blog/java/snmp/creating-snmp-agent-server-in-java-using-snmp4j/

`List oidList = impl.getOidList(); //从数据库中获取数据

对于(Oid oid:oidList){

   agent.registerManagedObject(MOScalarFactory.createReadOnly(new OID(
                oid.getOid()), oid.getValue()));

    }'

我正在尝试使用数据库中的数据注册托管对象。这个对吗?尽管 oid 是唯一的,但我在第二行收到重复注册异常。

`.1.3.6.1.4.1.1166.1.6.1.2.2.1.3.1.1

.1.3.6.1.4.1.1166.1.6.1.2.2.1.3.1.2`

我认为这不是正确的方法,因为如果数据库很大怎么办?非常感谢任何帮助/提示。

4

2 回答 2

3

问题

您会得到org.snmp4j.agent.DuplicateRegistrationException,因为 ContextScope 中只能有一个 ManagedObject。每个注册都将ManagedObject值分配给MOContextScope。第二次注册尝试将第二个对象设置为 contextScope。范围已满,因此引发异常。无论如何,每个标量值都应该以 .0 结尾。您可以检查任何 MIB 浏览器,如 iReasoning 并选择任何值。如果此值是标量 - 自动附加尾随零,尽管 MIB 文件中未提及它。所以最“正确”的方法是使用 4.1 解决方案。

解决方案 1 - 拥有 MOScalar

编写自己的 MOScalar。边界更小。您应该覆盖 getLowerBound、getUpperBound、isLowerIncluded、isUpperIncluded 来为您的对象获取单独的 contextScopes。

我建议每次都返回标量 OID 并包括两个边界。上限和下限更好地返回您已确定的相同 OID。

解决方案 2 - 拥有 MOServer

编写自己的 MOServer。与 blackJack 和其他人......尽管有这个,大多数情况下你可以简单地复制粘贴代码

private SortedMap<MOScope, ManagedObject> registry;

它应该看起来像这样

private SortedMap<MOScope, Set<ManagedObject>> registry;

并且会影响注册、注销等逻辑。DefaultMOServer - 678 行,包括。注释。事实上,你应该修复几个类:

query.matchesQuery(对象)

private boolean matchesQuery(MOQuery query, ManagedObject object) {
    if ((query.matchesQuery(object)) && object.getScope().isOverlapping(query.getScope()))
        if (object instanceof MOScalar) {
            MOScalar moScalar = (MOScalar) object;
            return query.getLowerBound().compareTo(moScalar.getID()) <= 0 &&
                    query.getUpperBound().compareTo(moScalar.getID()) >= 0;
        } else {
            return true;
        }

    return false;
}

protected void fire...事件(ManagedObject 对象,MOQuery 查询){

protected void fire...Event(Set<ManagedObject> objects, MOQuery query) {
        if (lookupListener != null) {
            for (ManagedObject mo : objects) {

ManagedObject other = lookup(new DefaultMOQuery(contextScope));

Set<ManagedObject> other = lookup(new DefaultMOQuery(contextScope), false);

等等...

解决方案 3 - 表格

使用表格行。您可以添加表格并追加行。

您将能够访问单元格作为

<tableEntryOID>.<columnSubID>.<rowIndexOID>

您可以将此问题用作教程。

解决方案 4 - OID 修复

让你 oid 使用不同的 contextScopes。

解决方案 4.1 添加尾随零

    agent.registerManagedObject(
            MOScalarFactory.createReadOnly(
                    new OID(oid.getOid()).successor(),
                    oid.getValue()
            )
    );

这会将.0附加到同级属性。

snmpget -v2c -c public localhost:2001 oid.getOid().0

此外,任何 MIB 浏览器都会将 .0 附加到 MIB 文件中定义的每个标量 oid。您可以使用 iReasoning 作为最流行的浏览器进行检查。甚至 hrSystemUptime (.1.3.6.1.2.1.25.1.1 - 见左下角) 也被请求为顶部的 hrSystemUptime.0 (.1.3.6.1.2.1.25.1.1.0)。

解决方案 4.2 在底部分离 OID。

static final OID sysDescr1 = new OID("1.3.6.1.4.1.5.6.1.8.9"),
        sysDescr2 = new OID("1.3.6.1.4.1.5.6.2.2.5");

修复数据库 OID 以获得单独的 contextScopes。

此外

您可以尝试阅读 SNMP4J-Agent-Instrumentation-Guide.pdf。顺便说一句,这对我没有帮助。
您可以将源附加到您的 IDE 以了解零预告片和其他细微差别。这对我获得有关 DefaultMOServer 的更多信息有很大帮助。

正确pom.xml导入以获取最新版本

    <repositories>
        <repository>
            <id>SNMP4J</id>
            <url>https://oosnmp.net/dist/release/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.snmp4j</groupId>
            <artifactId>snmp4j-agent</artifactId>
            <version>2.3.2</version>
        </dependency>
    </dependencies>
于 2015-05-08T17:54:06.043 回答
1

首先,OID 确实以数字开头,而不是点。您使用的语法来自 NET-SNMP 并且是非标准的。

其次,请阅读 SNMP4J-Agent-Instrumentation-Guide.pdf 文档,该文档详细描述了如何为 MIB 检测代理。您得到了重复注册异常,因为您将标量注册为子树。标量 OID 必须以“.0”实例后缀结尾。

使用 CommandResponder 接口是一种重新发明轮子。当您从头开始时,您很可能永远无法实现安全且符合标准的 SNMP 代理。使用 SNMP4J-Agent 及其检测挂钩将为您节省大量工作和麻烦。

于 2014-04-25T00:18:54.227 回答