You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:52:06