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

注册自定义OID处理器报错:MsgAndPduDispatcher无getNextReqMsgID属性

解决pysnmp中'MsgAndPduDispatcher'无'getNextReqMsgID'属性的错误

问题场景

尝试用pysnmp编写SNMP服务端,注册自定义OID响应GET请求时,触发错误:

AttributeError: 'MsgAndPduDispatcher' object has no attribute 'getNextReqMsgID'

错误出现在这行代码:

reqMsgID = snmpEngine.msgAndPduDsp.getNextReqMsgID()

问题原因

  1. 当前使用的pysnmp版本已移除MsgAndPduDispatcher.getNextReqMsgID()方法,原有调用方式失效
  2. 直接操作msgAndPduDsp注册OID的方式不符合pysnmp标准用法,正确做法是通过MIB仪器化(Instrumentation)实现自定义OID的响应逻辑

修正后的完整代码

from pysnmp.carrier.asyncio.dgram import udp
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdresp
from pysnmp.smi import builder, exval, rfc1902
from pysnmp.proto import rfc1902

# 创建SNMP引擎实例
snmpEngine = engine.SnmpEngine()

# 加载自定义MIB(不需要可跳过此段)
mibBuilder = snmpEngine.getMibBuilder()
mibPath = mibBuilder.getMibSources() + (builder.DirMibSource('/home/pi/'),)
mibBuilder.setMibSources(*mibPath)
mibBuilder.loadModules('MY-MIB')

# 自定义OID处理函数
def custom_oid_handler(snmp_engine, context_engine_id, context_name, var_binds, cb_ctx):
    results = []
    for oid, val in var_binds:
        if oid == (1, 3, 6, 1, 4, 1, 123456, 1):
            # 返回自定义字符串值
            results.append((oid, rfc1902.OctetString("Custom value for OID 1.3.6.1.4.1.123456.1")))
        else:
            # 未知OID返回标准错误
            results.append((oid, exval.noSuchObject))
    cb_ctx['cbFun'](snmp_engine, context_engine_id, context_name, results, cb_ctx)

# 绑定处理函数到MIB仪器控制器
mibInstrum = snmpEngine.msgAndPduDsp.mibInstrumController
mibInstrum.registerReadVarsCallback(custom_oid_handler)

# 创建UDP服务端传输
udpServerTransport = udp.UdpTransport().openServerMode(('0.0.0.0', 161))

# 配置SNMPv1社区字符串
community = config.CommunityData('public')
config.addV1System(snmpEngine, 'my-area', community)

# 配置VACM访问控制,允许读取1.3.6开头的OID树
config.addVacmUser(snmpEngine, 1, 'my-area', 'noAuthNoPriv', (1, 3, 6), (1, 3, 6))

# 启动SNMP命令响应器(处理GET/SET请求)
cmdresp.CmdResponder(snmpEngine)
snmpEngine.transportDispatcher.registerTransport(udpServerTransport)
snmpEngine.transportDispatcher.jobStarted(1)

print("SNMP server listening on port 161")

# 启动事件循环维持服务运行
try:
    snmpEngine.transportDispatcher.runDispatcher()
except Exception as e:
    snmpEngine.transportDispatcher.closeDispatcher()
    raise e

关键修正点

  • 补全缺失的engine、config、cmdresp核心模块导入
  • 移除错误的getNextReqMsgID调用和registerContextEngineId用法,改用registerReadVarsCallback注册自定义OID读取逻辑
  • 替换NotificationReceiver为CmdResponder:前者仅处理SNMP陷阱/通知,后者才是处理GET/SET请求的正确组件
  • 完善事件循环逻辑,确保服务持续运行

内容的提问来源于stack exchange,提问作者otuga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:20:39