一、问题描述
我想编写一个与本地 SNMP 代理进行通信的客户端程序,由于 SNMP代理是位于本地主机上,于是 客户端中 target地址采用回环地址。另外,SNMP代理的共同体设置为“private-xxq”,权限设置为“只读”,可以接收的SNMP包指定为“本机”(这些配置如图1-1所示)。同样地,在原程序中也使用与本地 SNMP代理相同的共同体。部分源码如下。我运行程序后,出现“SNMP request time out”的错误提示。
图1-1
部分代码为:
Snmp::socket_startup(); CTarget target(IpAddress("127.0.0.1"), "private-xxq", "private-xxq"); target.set_version(version1); Vb vb("1.3.6.1.2.1.1.1.0"); Pdu pdu; pdu += vb; int status; Snmp snmp(status); if (SNMP_CLASS_SUCCESS != status) { cout << snmp.error_msg(status) << endl; return -1; } cout << "目的IP:" << target.get_address().get_printable() << " 版本号:" << target.get_version() << endl; cout << "read共同体:" << target.get_readcommunity() << " write共同体:" << target.get_writecommunity() << endl; if ( (status = snmp.get(pdu, target)) == SNMP_CLASS_SUCCESS ) { pdu.get_vb(vb, 0); cout << "System Descriptor =" << vb.get_printable_value() << endl; } else { cout << snmp.error_msg(status) << endl; return -1; } Snmp::socket_cleanup();
将目标主机的 IP 由回环地址127.0.0.1更改为实际的 IP。
三、问题原因
本地SNMP代理只接收本地第一块网卡上传来的SNMP数据包。另外,我猜测本地SNMP代理是这样的:它获得本地的主机名,根据主机名通过DNS服务获得本地IP地址,利用获得的本地IP地址填充套接口地址,然后将该套接口地址绑定到UDP套接口。
四、总结——如何分析导致SNMP request time out问题出现的原因(仅供参考,并不保证正确性)
首先,我们需要明确 SNMP 属于应用层的协议,其传输层采用的协议是 UDP。所以,分析导致SNMP request time out问题出现的原因,本质就是分析 一个 UDP 通信的双方。下面列出所有我可以想到的情况:
情况1:SNMP代理根本没启动。这种情况下出现 time out很容易理解。
情况2:SNMP代理配置原因。只要出现下列情况之一,都会导致 time out。
a)SNMP代理与客户端(我们自己编写的与 SNMP代理进行通信的程序)使用的共同体不一致;
b)SNMP代理不接受你的主机发来的 SNMP包;
c)SNMP的权限是通知(通知意味着 SNMP包的发起方是SNMP代理,你写的客户端只负责回应);
情况3:客户端中 target的 IP使用回环地址(这正是本人遇到的问题);
情况4:客户端中请求的端口不是161。我想这种情况很少发生,但是你有机会可以在客户端指定 target的端口,像这样:CTarget target(UdpAddress("10.116.2.18:161"), "private-xxq", "private-xxq");
情况5:生成 snmplib.lib时的预处理器设置与客户端的预处理器“额外的设置”不一致,这里的“额外的设置”可以是这样的情况:生成 snmplib.lib,预处理器添加了 _NO_SNMPv3,而客户端中的工程属性中的预处理器没有添加 _NO_SNMPv3。有人说,双方“额外的设置”不一致会导致 SNMP request time out(见链接http://bbs.csdn.net/topics/360120200)。我试验后发现,不仅会导致 SNMP request time out,还会导致程序崩溃。