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