0一、课程设计目的以及要求1)课程设计目的随着网络规模的不断扩大,网络结构也变得越来越复杂。用户对网络应用的需求不断提高,企业和用户对计算机网络的依赖程度也越来越高。在这种情况下,企业的管理者和用户对网络的性能、运行状况以及安全性也越来越重视。一个有效且实用的网络每时每刻都离不开网络管理。网络管理是监督、组织和控制网络通信服务和信息处理所必需的各种活动的总称。除了专门的标准化组织制定了一些标准外,一些网络发展比较早的机构与厂家也制定了一些在各自网络上应用的管理标准,其中应用最广泛的是简单网络管理协议(SimpleNetworkManagementProtocol,SNMP)。SNMP是由IETF提出的面向Internet的管理协议,其管理对象包括网桥、路由器、交换机等内存和处理能力有限的网络互连设备。SNMP由于其简单性得到了业界广泛的支持,成为目前最流行的网络管理协议。本课程设计的目的是通过编程实现SNMP协议,从而加深对SNMP协议的理解。2)课程设计要求熟悉SNMP协议后,按如下要求编写程序,实现SNMP协议,获取路由器中的相关信息。A)采用VC6.0进行编程。B)根据某路由器的IP及共同体名,获得该路由器的系统信息。C)获取路由器的IP地址信息以及路由表信息;二、原理分析网管系统是指课管理真个网络及其中的网络设备的软件系统。网管系统设计4个方面的内容:网管功能、资源、信息及结构。其中,网管功能由ISO网络管理功能域定义:网管资源的表示涉及资源的表示方法,主要包括网络中硬件,软件与服务等资源;网管信息的表示方法与传输方式,由网管系统采用的网络管理协议决定;网管系统的结构主要包括两层结构与三层结构。1SNMP网管系统采用客户机/服务器工作模式。SNMP网管系统包括两个组成部分:SNMP客户机与SNMP服务器。其中,SNMP客户机是SNMP服务的请求者,他安装在网管管理工作站中,通常被称为SNMP管理器:SNMP服务器是SNMP服务的响应者,它安装在支持SNMP服务的网络设备中,通常被称为SNMP代理。管理信息保存在SNMP代理的MIB中。SNMP服务在传输层采用UDP协议,在传输管理信息之前不需要先建立连接。需要注意的是,SNMP代理主动发送Trap信息给SNMP管理器。三、基本思路及关键问题的解决方法1)程序流程图程序流程图如图1所示:显示相关信息结束开始实例化CSnmp,并用IP和团体名初始化调用CSnmp类中的Prepare函数,完成SNMP的加载、会话的建立等填充请求列表,列表中存放的实际上是objectID调用CSnmp类中的GetTable函数,根据请求列表查路由表信息,放到一个CRouter类里释放资源2图1程序流程图2)基本思路首先,加载SNMP(包括SNMP主版本号、SNMP副版本号、支持的最高操作标准、默认的实体/上下文传输模式以及默认的重发机制);建立会话,在此过程中得到的会话句柄非常重要;设置传输模式SnmpSetTranslateMode和重传模式SnmpSetRetransmitMode,这两个函数的参数就是加载SNMP时使用的传输模式以及重发机制;创建实体HSNMP_ENTITY,第一个参数是步骤2中得到的句柄。IP可以是发送消息的网络设备的IP地址或接收消息的管理设备的IP地址,通过需要具体创建实体——hSrcEntity、hDestEntity;对源实体和目的实体设置超时时间和重传次数——SnmpSetTimeout、SnmpSetRetry;建立上下文句柄——HSNMP_CONTEXT、hContext;建立变量捆绑列表;设置PDU格式,要正确发送数据必须采用特定的PDU格式;发送SNMP命令——SnmpSendMsg;接收SNMP响应;等到响应成功就释放资源。3)关键问题及解决方案1.如何设置PDU格式PDU是SNMP数据包的一个部分,它包括请求标识符、错误状态、错误索引以及捆绑的变量名称。因此设置PDU格式是此程序的关键部分。HSNMP_PDUhPdu;hPdu=SnmpCreatePdu(hSession,SNMP_PDU_GETNEXT,0,NULL,NULL,hVbl)第二个参数是PDU类型,有多种操作方式:SNMP_PDU_GETNEXT用来在不了解该表时获取第一个组值,SNMP_PDU_GET用来获得某个对象某个对象标识符的值;SNMP_PDU_SET用来修改某个对象标识符的值。2.如何接收和响应SNMP要接收和响应SNMP就先得创建实体,然后SNMP管理器调用函数,接收从SNMP代理返回的SNMP响应,SNMP管理器需要解析SNMP响应数据包,对各个字段逐个进行分析与判断,SNMP管理器需要分析错误类型字段,判断是否成功完成对管理对象的操作。hSrcEntity=SnmpStrToEntity(hSession,(LPCSTR)GetLocalIP());hDestEntity=SnmpStrToEntity(hSession,ip);四、源代码3#includewinsock2.h#includeWinsnmp.h#includestring#includevector#includealgorithm#includeiostream#pragmacomment(lib,wsnmp32.lib)#pragmacomment(lib,ws2_32.lib)usingnamespacestd;typedefvectorstringstrvec;typedefvectorstrvecstrvec_vec;classCManager{public:CManager(stringstrIP,stringstrCommunity);//构造函数~CManager();//析构函数stringValueToString(smiVALUEsValue);//返回值转换boolInitSnmp();//用于加载SNMPboolSend(conststrvec&strOIDArray,smiINTsPDUType=SNMP_PDU_GETNEXT);boolReceive(HSNMP_VBL&hVbl);//接收应答包boolGetAValue(conststring&strOID,string&strResult);//获取ObjectID值boolGetTable(strvecstrOIDArray,strvec_vec&strResultTable);stringGetLocalIP();//获取本机IP地址voidErrorMessage(stringstrMessage);//输出错误信息voidSetEvent();protected:HSNMP_SESSIONm_hSession;//会话句柄HSNMP_CONTEXTm_hContext;//上下文句柄staticSNMPAPI_STATUSCALLBACKCallback(HSNMP_SESSIONhSession,//WinSNMP会话句柄HWNDhWnd,//处理通知窗口的句柄UINTwMsg,//窗口消息通知码WPARAMwParam,//消息类型LPARAMlParam,//PDU的请求标识符LPVOIDlpClientData//可选的自定义数据);private:smiUINT32m_nMajorVersion;//WinSNMPAPI主版本smiUINT32m_nMinorVersion;//WinSNMPAPI副版本smiUINT32m_nLevel;//支持最高的操作标准smiUINT32m_nTranslateMode;//默认实体/上下文模式smiUINT32m_nRetransmitMode;//默认的重发机制stringm_IP;//IP地址smiOCTETSm_Community;//团体名4HANDLEm_hEvent;};//构造函数CManager::CManager(stringstrIP,stringstrCommunity):m_nMajorVersion(0),m_nMinorVersion(0),m_nLevel(0),m_nTranslateMode(0),m_nRetransmitMode(0),m_IP(strIP){m_Community.len=strCommunity.length();m_Community.ptr=newsmiBYTE[strCommunity.length()];memcpy(m_Community.ptr,strCommunity.c_str(),strCommunity.length());m_hEvent=CreateEvent(NULL,true,false,NULL);}//析构函数CManager::~CManager(){SnmpFreeContext(m_hContext);SnmpClose(m_hSession);SnmpCleanup();delete[]m_Community.ptr;}//SNMP初始化函数boolCManager::InitSnmp(){//加载SNMPif(SnmpStartup(&m_nMajorVersion,&m_nMinorVersion,&m_nLevel,&m_nTranslateMode,&m_nRetransmitMode)==SNMPAPI_FAILURE){ErrorMessage(startupSNMPerror!);returnfalse;}//设置传输模式if(SnmpSetTranslateMode(m_nTranslateMode)==SNMPAPI_FAILURE){ErrorMessage(Settransfermodeerror!);returnfalse;}//设置重传模式if(SnmpSetRetransmitMode(m_nRetransmitMode)==SNMPAPI_FAILURE){ErrorMessage(Setretransmissionmodeerror!);returnfalse;}5//建立会话m_hSession=SnmpCreateSession(NULL,NULL,CManager::Callback,(LPVOID)this);if(m_hSession==SNMPAPI_FAILURE){ErrorMessage(Setconversationerror!);returnfalse;}//建立实体HSNMP_ENTITYhEntity;if((hEntity=SnmpStrToEntity(m_hSession,m_IP.c_str()))==SNMPAPI_FAILURE){ErrorMessage(Createntityerror!!);returnfalse;}//建立上下文句柄if((m_hContext=SnmpStrToContext(m_hSession,&m_Community))==SNMPAPI_FAILURE){ErrorMessage(Createcontexthandleerror!!);returnfalse;}//设置超时时间if(SnmpSetTimeout(hEntity,10)==SNMPAPI_FAILURE){ErrorMessage(Settimeouterror!);returnfalse;}//设置重传次数if(SnmpSetRetry(hEntity,1)==SNMPAPI_FAILURE){ErrorMessage(Setretransmissionserror!);returnfalse;}returntrue;}//SNMP消息发送函数boolCManager::Send(conststrvec&strOIDArray,smiINTsPDUType){HSNMP_VBLhVbl;HSNMP_PDUhPdu;smiOIDsOid;HSNMP