SNMP4J中SNMP表映射POJO及表结构识别技术问题
SNMP4J相关问题解答
问题1:如何判断一个OID对应的是表结构还是树形结构?
有三种实用方法:
- 查MIB定义:直接查看目标OID所属的MIB文件,表类型的节点会被明确标记为
TABLE(比如ipAddrTable在IP-MIB里就是TABLE类型),普通树形节点则是OBJECT-TYPE且无TABLE属性。 - 分析OID后缀结构:表结构的OID下,所有叶子节点的OID都会带有动态行索引后缀(比如
ipAddrTable的列OID.1.3.6.1.2.1.4.20.1.1后面会跟着IP地址拆分的十进制数字,作为行唯一标识);普通树形结构的子节点OID是固定的,不会有这种动态变化的后缀。 - SNMP命令测试:用
snmpwalk工具请求目标OID,如果返回的结果都是同一前缀+不同索引后缀的OID集合,那就是表结构;如果返回固定数量的子节点,就是普通树形结构。例如执行:
若返回的每条结果OID都带有IP拆分的后缀,说明是表结构。snmpwalk -v2c -c private 10.10.10.2 .1.3.6.1.2.1.4.20
问题2:如何从TableEvent中识别行和列,填充IpAddress列表?
先明确IP-MIB::ipAddrTable的关键列OID
对应你的IpAddress POJO,需要映射的三个列OID如下:
| POJO字段 | 对应SNMP列名 | 列OID |
|---|---|---|
| ip | ipAdEntAddr | .1.3.6.1.2.1.4.20.1.1 |
| index | ipAdEntIfIndex | .1.3.6.1.2.1.4.20.1.2 |
| netmask | ipAdEntNetMask | .1.3.6.1.2.1.4.20.1.3 |
修改SNMP4J代码逻辑
每个TableEvent对象对应表中的一行数据,event.getColumns()返回该行所有列的VariableBinding数组。通过匹配列OID前缀提取对应字段值,修改后的doWalkTable方法核心逻辑如下:
// 定义表列的OID常量 private static final OID IP_AD_ENT_ADDR = new OID(".1.3.6.1.2.1.4.20.1.1"); private static final OID IP_AD_ENT_IF_INDEX = new OID(".1.3.6.1.2.1.4.20.1.2"); private static final OID IP_AD_ENT_NET_MASK = new OID(".1.3.6.1.2.1.4.20.1.3"); public static List<IpAddress> doWalkTable(String tableOid, Target<Address> target) throws IOException { List<IpAddress> ipAddressList = new ArrayList<>(); TransportMapping<? extends Address> transport = new DefaultUdpTransportMapping(); Snmp snmp = new Snmp(transport); transport.listen(); TableUtils tableUtils = new TableUtils(snmp, new DefaultPDUFactory()); List<TableEvent> events = tableUtils.getTable(target, new OID[]{new OID(tableOid)}, null, null); if (events == null || events.size() == 0) { System.out.println("Error: Unable to read table..."); return ipAddressList; } for (TableEvent event : events) { if (event == null || event.isError()) { if (event != null) { System.out.println("Error: table OID [" + tableOid + "] " + event.getErrorMessage()); } continue; } VariableBinding[] varBindings = event.getColumns(); if (varBindings == null || varBindings.length == 0) { continue; } // 初始化当前行的IpAddress对象 IpAddress currentIpAddr = new IpAddress(); // 遍历当前行的所有列,匹配对应字段 for (VariableBinding vb : varBindings) { if (vb == null) continue; OID vbOid = vb.getOid(); Variable var = vb.getVariable(); if (vbOid.startsWith(IP_AD_ENT_ADDR)) { currentIpAddr.setIp(var.toString()); } else if (vbOid.startsWith(IP_AD_ENT_IF_INDEX)) { currentIpAddr.setIndex(var.toString()); } else if (vbOid.startsWith(IP_AD_ENT_NET_MASK)) { currentIpAddr.setNetmask(var.toString()); } } // 确保核心字段不为空再加入列表 if (currentIpAddr.getIp() != null && currentIpAddr.getNetmask() != null) { ipAddressList.add(currentIpAddr); } System.out.println("------------------------------------------------------"); } snmp.close(); return ipAddressList; }
逻辑说明
- 每个
TableEvent对应一行数据,跳过错误事件和空事件。 - 遍历当前行的所有
VariableBinding,通过vbOid.startsWith()匹配列的OID前缀,区分不同字段。 - 将SNMP变量的字符串值直接赋值给IpAddress对象的对应字段,最后校验核心字段非空后加入列表。
内容的提问来源于stack exchange,提问作者mah454
相关产品推荐
相关产品推荐

