我是snmp并使用snmp4j创建snmp代理的新手。我的java应用程序需要监听snmp请求并根据传入的oid查询db并发回响应。我有snmp代理的src代码。但是代理如何根据传入的oid查询数据库?我是否需要在我的数据库中将所有oid注册为代理中的托管对象,以便代理可以在请求到达时进行查找?或换句话说,我如何从代理指向我的数据存储区/数据库?
这是我正在使用的代码。
http://shivasoft.in/blog/java/snmp/creating-snmp-agent-server-in-java-using-snmp4j/
`List oidList = impl.getOidList(); //从db
获取数据for(Oid oid:oidList){
agent.registerManagedObject(MOScalarFactory.createReadOnly(new OID(
oid.getOid()), oid.getValue()));
}'
我正在尝试使用db中的数据注册托管对象。它是否正确? 我在第二行收到重复的注册例外,虽然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`
我不认为这是正确的方法,因为如果db是巨大的呢? 非常感谢任何帮助/提示。
答案 0 :(得分:3)
您获得 org.snmp4j.agent.DuplicateRegistrationException ,因为ContextScope中只能有一个ManagedObject。每次注册都会为ManagedObject分配MOContextScope值。第二次注册尝试将第二个对象设置为contextScope。范围已经填充,因此抛出异常。 但是每个标量值应该最终得到.0。您可以检查任何MIB浏览器,如iReasoning并选择任何值。如果此值是标量 - 尽管在MIB文件中未提及,但是会自动附加尾随零。所以最多"正确"方法是使用4.1解决方案。
编写自己的MOScalar。有更小的界限。 你应该覆盖getLowerBound,getUpperBound,isLowerIncluded,isUpperIncluded来为你的对象获取单独的contextScopes。
我建议每次返回Scalar OID并包含两个边界。 上边界和下边界最好返回相同的OID。
编写自己的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);
等等......
使用表格行。 您可以添加表并追加行。
您将能够以
的形式访问单元格<tableEntryOID>.<columnSubID>.<rowIndexOID>
您可以使用this question作为教程。
让你使用不同的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以获取单独的contextScope。
您可以尝试阅读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>
答案 1 :(得分:1)
首先,OID确实以一个数字开头 - 而不是一个点。您使用的语法来自NET-SNMP,并且是非标准的。
其次,请阅读SNMP4J-Agent-Instrumentation-Guide.pdf文档,该文档详细描述了如何为MIB设置代理。您获得了重复的注册异常,因为您将标量注册为子树。标量OID必须以“.0”实例后缀结束。
使用CommandResponder接口有点重新发明轮子。当您从头开始时,您很可能永远无法实现安全且标准的符合SNMP代理。使用SNMP4J-Agent及其检测钩子将为您节省大量工作和麻烦。