如何用Java的SNMP4J实现带-Ox参数的snmpwalk获取原始值?
问题
部分思科设备执行snmpwalk时,会自动将十六进制值转换为ASCII。通过命令行snmpwalk -Os -Ox -c <community> -v 2c <ip_address> <OID>可获取原始十六进制值(格式为Hex-STRING: <result_as_hex>),但使用SNMP4J调用VariableBinding.toValueString()时,得到的是ASCII值,与不带-Ox参数的snmpwalk结果一致。需要通过SNMP4J实现类似-Ox的功能,获取原始十六进制值。
当前代码如下:
public Map<String, String> doWalk(String tableOid, Target target) throws IOException { log.info("doWalk({}, {})", tableOid, target); Map<String, String> result = new TreeMap<>(); TransportMapping<? extends Address> transport = new DefaultUdpTransportMapping(); log.info(transport.getListenAddress().toString()); Snmp snmp = new Snmp(transport); transport.listen(); TreeUtils treeUtils = new TreeUtils(snmp, new DefaultPDUFactory()); List<TreeEvent> events = treeUtils.getSubtree(target, new OID(tableOid)); if (events == null || events.isEmpty()) { log.info("Error: Unable to read table..."); return result; } log.info("event size is {}", events.size()); for (TreeEvent event : events) { if (event == null) { continue; } if (event.isError()) { log.info("Error: table OID [{}] {}", tableOid, event.getErrorMessage()); continue; } VariableBinding[] varBindings = event.getVariableBindings(); if (varBindings == null || varBindings.length == 0) { continue; } for (VariableBinding varBinding : varBindings) { if (varBinding == null) { continue; } result.put("." + varBinding.getOid().toString(), varBinding.toValueString()); } } snmp.close(); return result; }
解决方案
要实现snmpwalk -Ox的效果,需针对OctetString类型的变量手动处理,避免toValueString()自动转换为ASCII的逻辑:
修改核心循环逻辑
替换原代码中遍历VariableBinding的部分为以下代码:
for (VariableBinding varBinding : varBindings) { if (varBinding == null) { continue; } String oidStr = "." + varBinding.getOid().toString(); Variable variable = varBinding.getVariable(); String valueStr; if (variable instanceof OctetString) { // 获取原始字节数组并转换为十六进制字符串 byte[] rawBytes = ((OctetString) variable).toByteArray(); StringBuilder hexBuilder = new StringBuilder(); for (byte b : rawBytes) { hexBuilder.append(String.format("%02X ", b)); } // 移除末尾多余空格 valueStr = hexBuilder.length() > 0 ? hexBuilder.substring(0, hexBuilder.length() - 1) : ""; // 可选:添加与snmpwalk一致的前缀 // valueStr = "Hex-STRING: " + valueStr; } else { // 非字节类型变量仍使用原有方法 valueStr = variable.toValueString(); } result.put(oidStr, valueStr); }
关键说明
- 思科设备返回的十六进制数据在SNMP4J中对应
OctetString类型,toByteArray()可直接获取原始二进制字节 - 使用
%02X格式化每个字节为两位大写十六进制,与snmpwalk -Ox的输出格式保持一致 - 非
OctetString类型的变量(如整数、OID等)无需特殊处理,继续使用toValueString()即可
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

