簡單SNMP管理程序的VC++代碼實例實現

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

 

引自 http://www.wangwa.com/info/2006-11/38020p2.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章