简单SNMP管理程序的VC+代码实例实现
[
2007-6-10 23:56:00
| 发表者 :
zihe
]
友情提醒: snmp(simple network management protocol)是基于tcp/ip的网络管理协议,关于其工作原理网上很多,百度一下或者看看msdn,今天在这里记一下实现的步骤,本人工作环境是windows xp professional sp2 + microsoft visual studio .net 2003,不保证其他平台与本人的步骤一致。
一、安装snmp服务
先查看系统中是否已经安装有snmp服务,开始->运行->cmd->回车
输入命令“net start snmp”:
c:\documents and settings\mmpire>net start snmp
snmp service 服务正在启动 .
snmp service 服务已经启动成功。
c:\documents and settings\mmpire>
则已经安装有snmp,如果没有安装,则需先安装snmp服务:
1. 打开控制面板,双击[添加/删除程序];
2. 在弹出的[添加/删除程序]对话框的左窗格中,单击 [添加/删除 windows 组件];
3. 在弹出的[windows 组件向导]中双击 [管理和监视工具]。
4. 在弹出的[管理和监视工具] 对话框中,勾选[简单网络管理协议],单击 [确定]。
5. 安装协议时需要用到windows xp sp2安装盘,之后可能需要重启,不过我的机器没要求:p
再按前面的执行“net start snmp”命令启动snmp服务。
******************************************************************
二、代码示例
这种编程一般都有套路,即需要遵循一定的格式,ms提供了snmp编程的样例代码,这个样例是一个最简单的snmp管理程序,用户通过输入snmp命令来进行交互。我们可以从中查看winsnmp的api的使用方法。所有样例代码都在platform sdk中,可以在下面的地址下载到最新版的platform sdk:
http://www.microsoft.com/downloads/details.aspx?familyid=484269e2-3b89-47e3-8eb7-1f2be6d7123a&displaylang=en
可以看看它的介绍(哈,几乎支持了所有现在的windows版本),只要下载全部17个psdk-full.*.cab及最后一个psdk-full.exe,之后全部解压缩并安装到某个文件夹中即可。
1. 找到示例代码
进入platformsdk\samples\netds\snmp,可以看到三个文件夹:snmputil,testdll,wsnmp以及一个makefile。其中snmputil与testdll是基于nt平台的,略去不说,具体参看内附的readme。而makefile是用来编译所有这三个文件里的模块的,对于xp平台前两个文件夹里的模块不能正确编译,所以也不看。进入wsnmp文件夹,我们需要的示例代码就在这里。将五个文件全拷贝到d盘根目录。
2. 编译示例代码
从以下路径打开vc.net命令行窗口:
开始->所有程序-> visual studio .net 2003->visual studio .net 2003 命令提示。
vc6下的路径差不多,自己找一下。打开窗口之后输入以下命令:
c:\documents and settings\mmpire>d:
d:\>nmake all
microsoft (r) 程序维护实用工具 7.10.3077 版
版权所有 (c) microsoft corporation。保留所有权利。
if not exist "win2000_debug/" mkdir win2000_debug cl -zi -od -ddebug -c -dcrtapi1=_cdecl -dcrtapi2=_cdecl -nologo -d_x86_=1-dwin32 -d_win32 -w3 -d_winnt -d_win32_winnt=0x0500 -d_win32_ie=0x0500 –dwinv er=0x0500 -d_mt -mtd /fo"win2000_debug\\" /fd"win2000_debug\\" wsnmputil.cpp wsnmputil.cpp cl -zi -od -ddebug -c -dcrtapi1=_cdecl -dcrtapi2=_cdecl -nologo -d_x86_=1 -dwin32 -d_win32 -w3 -d_winnt -d_win32_winnt=0x0500 -d_win32_ie=0x0500 –dwinv er=0x0500 -d_mt -mtd /fo"win2000_debug\\" /fd"win2000_debug\\" helper.cpp helper.cpp link /debug:full /debugtype:cv /incremental:no /nologo -subsystem:conso le,5.0 kernel32.lib ws2_32.lib mswsock.lib advapi32.lib -out:win2000_debug\wsnm putil.exe win2000_debug\wsnmputil.obj win2000_debug\helper.obj user32.lib gdi32.lib snmpapi.lib wsnmp32.lib mgmtapi.lib oldnames.lib
d:\>
可以发现当前目录下出现一个子目录win2000_debug,也可以用nmake删除:
d:\>nmake clean
microsoft (r) 程序维护实用工具 7.10.3077 版
版权所有 (c) microsoft corporation。保留所有权利。
if exist win2000_debug/ rd /s /q win2000_debug
d:\>
当然现在我们还需要它,根据其readme文件所述,这个示例代码是一个snmp管理程序(snmp manager application),展示了如何使用winsnmp的api编写应用程序。它支持snmp 1的get,getnext,set操作,以及snmp2的getbulk操作。而扩展的walk和subtree操作则使用getnext操作来实现。
3. 测试示例
①监听snmp的端口
d:\>cd win2000_debug
d:\win2000_debug>wsnmputil trap
wsnmputil: listening for traps...
②另外打开一个vc.net命令行窗口
d:\win2000_debug>net stop snmp
snmp service 服务正在停止..
snmp service 服务已成功停止。
d:\win2000_debug>net start snmp
snmp service 服务正在启动 .
snmp service 服务已经启动成功。
d:\win2000_debug>
③按照其readme里所描述的,在第一个监听窗口会出现以下信息
d:\win2000_debug>wsnmputil trap
wsnmputil: listening for traps...
agent : 127.0.0.1
oid :1.3.6.1.2.1.1.3.0
oid string: system.sysuptime.0
timeticks: 0
(注:…太长…略去)
可惜在本人机器上,第一个窗口始终没有反应,似乎snmp服务启动时会向局域网发送snmp的数据包,但我不确定,以后解决了再写。
④再测试几个命令
d:\win2000_debug>wsnmputil
usage: wsnmputil [-v1|-v2] [get|getnext|walk|getbulk|subtree] agent community [
non_repeaters max_repetitions] oid [oid ...]
examples:
wsnmputil trap
wsnmputil -v1 get localhost public 1.3.6.1.2.1.1.1.0
wsnmputil -v1 getnext localhost public 1.3.6.1.2.1.1.1.0
wsnmputil -v1 subtree localhost public 1.3.6.1.2.1.1
wsnmputil -v1 set toaster public 1.3.6.1.4.1.12.2.5.0 2
wsnmputil -v2 walk localhost public 1
wsnmputil -v2 getbulk toaster public 1 2 1.3.6.1.2.1.1.2.0 1.3.6.1.2.1.4.2
2.1.2 1.3.6.1.2.1.4.22.1.4
d:\win2000_debug>wsnmputil -v2 walk localhost public 1
(注:….非常多的结果…不过现在还不知道什么意思…汗)
d:\win2000_debug>wsnmputil -v1 get localhost public 1
oid :1.3.6.1.2.1.1
system
null – null
d:\win2000_debug>wsnmputil -v1 getnext localhost public 1.3.6.1.2.1.1.1.0
(注: 1.3.6.1.2.1.1.1.0是在oidview里看到的,貌似是本人agent的地址)
oid :1.3.6.1.2.1.1.2.0
system.sysobjectid.0
object identifier - .1.3.6.1.4.1.311.1.1.3.1.1
******************************************************************
三、代码分析 一共三个文件:wsnmputil.h wsnmputil.cpp helper.cpp,具体代码在后面贴出,这里分析一下其大体结构:
1. wsnmputil.h
21个常量定义,一个结构体类型声明,一个globalvars类声明,以及19个函数声明。
2. helper.cpp
一些函数定义,比如输出提示消息,解析命令行输入的命令,调试信息,地址转换,输出oid地址以及psession的参数。
3. wsnmputil.cpp
程序骨干如下:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <winsock2.h> #include <winsnmp.h> #include <snmp.h> #include <mgmtapi.h> #include "wsnmputil.h" //外部全局变量gvars,记录用户命令等信息
globalvars gvars;
int main( int argc, char **argv ) { //初试化一般参数 psnmp_mgr_session psession = null; int nreturn = 0; bool result; int i = 0;
//初试化snmp参数
smiuint32 nmajorversion = 0; smiuint32 nminorversion = 0; smiuint32 nlevel = 0; smiuint32 ntranslatemode = 0; smiuint32 nretransmitmode = 0;
//接收用户在命令行输入的命令,主要记录在变量gvars中
parsecommandline( argc, argv );
//加载snmp服务
snmpstartup(&nmajorversion,&nminorversion,&nlevel,&ntranslatemode,&nretransmitmode);
//分两种情况设置传输模式(snmp1/snmp2)
if ( gvars.version == false ) snmpsettranslatemode( snmpapi_untranslated_v1 ); else snmpsettranslatemode( snmpapi_untranslated_v2 ); //为会话分配内存空间 psession = ( psnmp_mgr_session )snmputilmemalloc( sizeof( snmp_mgr_session ) );
/*创建一个隐藏的负责监听winsnmp消息的窗口,这是一段典型的调用createwindow()创建windows窗口的代码。(注:窗口处理函数是notificationwndproc(),本程序调用creatwindow()后返回,而由系统来创建窗口,其中就要调用这个窗口处理函数,这种由程序员编写而由系统调用的函数需要定义为callback函数)注意:snmp接收的数据包(pdu)就在窗口进程里处理*/
createnotificationwindow( psession ); //建立会话 snmpopen( psession->hwnd, wm_snmp_incoming ); //解析用户在命令行输入的命令 switch (gvars.operation) { case trap:waitfortraps( psession );break; case walk:createpdusendrequest( psession, null );break; case get: case get_next:result = createpdusendrequest( psession, null ); break; //创建一个pdu并发送一个请求 case get_bulk:result = createpdusendrequest( psession, null ); break; case sub_tree:result = createpdusendrequest( psession, null ); break; case set:result = createpdusendrequest( psession, null );break; //先探测所给agent是否存在,之后再发送设定消息 }
closewinsnmpsession ( psession );//关闭winsnmp任务,调用了snmpclose() snmputilmemfree( psession );//释放内存 snmpcleanup( );//清理工作 wsacleanup( );//关闭windows sockets return ( nreturn ); } //end of main() |
四、其他说明
1. 用vc编译
方法一:
建立工程并添加上述三个文件,这时可以编译通过,但链接是会出现许多错误,大多是“未能解析的符号”,这时我们还需要给工程添加一些库,操作路径如下:
项目->属性->链接器->命令行
在“附加选项”中加入
"user32.lib gdi32.lib snmpapi.lib wsnmp32.lib mgmtapi.lib oldnames.lib ws2_32.lib"
前面的lib库摘自其makefile,最后一个ws2_32.lib是google出来的:p
方法二:
打开vc.net,按以下操作路径:
文件->新建->项目->vc++项目->常规->生成文件项目->起个名字->确定->应用程序设置->在生成命令行里输入nmake->完成
然后把那三个文件及makefile拷贝到这个项目的目录下面,就可以编译了:
生成->生成解决方案
方法三:
前面说过了,打开vc的命令行窗口直接用nmake命令:p
上一篇:
VC+编程实现对火焰的计算机动态仿真 下一篇:
用C+实现跨平台游戏开发之Allegro引擎