微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SNMP++2.8中文文档

SNMP++

用C++构建的,处理简单网罗管理协议(SNMP)API

SNMP++.1

C++构建的,处理简单网罗管理协议(SNMP)API1

1.介绍...6

1.1.什么是SNMP++.6

1.2.SNMP++的本质...6

1.2.1.简单易用的SNMP++.6

1.2.2.编程安全的SNMP++.7

1.2.3.可移植的SNMP++.8

1.2.4.可扩充的SNMP++.8

2.一个介绍性的例子...9

2.1.一个简单的SNMP++例子...9

2.2.对介绍性例子的分析...9

3.SNMP++特性...10

3.1.完整的一套SNMPC++...10

3.2.SNMP内存的自动管理...10

3.3.简单易用的...10

3.4.强大灵活的...10

3.5.可移植对象的...10

3.6.自动超时和重发机制...10

3.7.阻塞模式...11

3.8.异步的非阻塞模式...11

3.9.NotificationTrap的收发...11

3.10.通过双效的API支持SNMPv1SNMPv2.11

3.11.支持SNMPGet,GetNext,GetBulk,Set,InformTrap的操作...11

3.12.通过继承实现重定义...11

4.在MicrosoftWindows系列操作系统上使用SNMP++.12

4.1.WinSNMPVersion1.1的使用...12

4.2.对IPIPX的支持...12

4.3.对NotificationTrap收发的支持...12

4.4.与HPOpenViewforWindows兼容...12

5.在UNIX上使用SNMP++.13

5.1.统一的类的接口...13

5.2.WindowsUNIX的仿真与移植...13

5.3.与HPOpenViewforUNIX兼容...13

6.SNMPSyntaxClasses.14

7.ObjectIdClass.15

7.1.对象标识符类...15

7.2.OidClass的成员函数列表...15

7.3.一些OidClass的例子...16

8.OctetStrClass.19

8.1.八位字节类...19

8.2.OctetStrClass的成员函数列表...19

8.3.注意...20

8.4.一些OctetStrClass的例子...21

9.TimeTicksClass.22

9.1.时间戳类...22

9.2.TimeTicksClass的成员函数列表...22

9.3.注意...22

9.4.一些TimeTicksClass的例子...23

10.Counter32Class.24

10.1.32位计数器类...24

10.2.Counter32Class的成员函数列表...24

10.3.一些Counter32Class的例子...24

11.Gauge32Class.26

11.1.容量类...26

11.2.Gauge32Class的成员函数列表...26

11.3.一些Gauge32的例子...26

12.Counter64Class.28

12.1.64位计数器类...28

12.2.Counter64Class的成员函数列表...28

12.3.一些的Counter64Class例子...29

13.AddressClass.30

13.1.什么是网络地址类?...30

13.2.为什么要使用网络地址类?...30

13.3.Addressclass.30

13.4.AddressClasses及其接口...30

13.5.IpAddressClass的特点...32

13.6.GenAddress的特点...32

13.7.AddressClass的有效性...32

13.8.UdpAddressesIpxSockAddresses.33

13.8.1.用UdpAddresses发送请求...33

13.8.2.用IpxSockAddresses发送请求...33

13.8.3.用UdpAddressIpxSockAddress接收Notification.33

13.9.有效的地址格式...33

13.10.AddressClass例子...34

14.TheVariableBindingClass.36

14.1.VariableBindingClass成员函数列表...36

14.2.VbClass的公有成员函数...37

14.2.1.VbClass的构造和析构函数...37

14.2.2.VbClassGetOid/SetOid成员函数...38

14.2.3.VbClassGetValue/SetValue成员函数...38

14.2.4.用一个GenAdress对象设置value.39

14.2.5.用一个UdpAdress对象设置value.39

14.2.6.用一个IpxSockAdress对象设置value.40

14.2.7.用一个Octet对象设置value部分...40

14.2.8.VbClass成员函数:GetValue.40

14.2.9.Vb对象的成员函数:GetSyntax.41

14.2.10.检查Vb对象的有效性...42

14.2.11.把Vb对象付给另一个Vb对象...42

14.2.12.Vb对象的错误信息...42

14.3.VbClass例子...42

15.PduClass.45

15.1.PduClass成员函数列表...45

15.2.PduClass的构造和析构...46

15.3.访问Pdu的成员函数...46

15.4.PduClass重载操作符...47

15.5.PduClass处理TrapsInforms的成员函数...47

15.6.加载Pdu对象...48

15.7.加载Pdu对象...48

15.8.卸载Pdu对象...49

16.SnmpMessageClass.50

17.TargetClass.51

17.1.抽象的Target51

17.2.Target地址...51

17.3.重发机制...51

17.4.TargetClass接口...51

17.5.CTargetClass(Community为基础的Target)52

17.5.1.CTarget对象可通过3种不同的方式构建...53

17.5.2.修改CTargets.53

17.5.3.访问CTargets.53

17.5.4.CTargets例子...54

18.SnmpClass.55

18.1.SnmpClass成员函数列表...55

18.2.双效的API56

18.3.SnmpClass的公共成员函数...57

18.3.1.SnmpClass的构造和析构函数...57

18.3.2.SnmpClass构造函数...57

18.3.3.SnmpClass析构函数...57

18.3.4.SnmpClass发送请求的成员函数...57

18.3.5.SnmpClass的阻塞方式成员函数:Get57

18.3.6.SnmpClass的阻塞方式成员函数:GetNext57

18.3.7.SnmpClass的阻塞方式成员函数:Set58

18.3.8.SnmpClass的阻塞方式成员函数:GetBulk.58

18.3.9.SnmpClass的阻塞方式成员函数:Inform..58

18.4.SnmpClass的异步方式成员函数...58

18.4.1.SNMP++异步回调函数的类型定义...58

18.4.2.取消一个异步请求...59

18.4.3.SnmpClass的异步成员函数:Get59

18.4.4.SnmpClass的异步成员函数:Set60

18.4.5.SnmpClass的异步成员函数:GetNext60

18.4.6.SnmpClass的异步成员函数:GetBulk.60

18.4.7.SnmpClass的异步成员函数:Inform..60

18.5.SNMP++通知的方法...60

18.5.1.发送Trap.61

18.5.2.接收Notification.62

18.5.3.使用OidCollection,TargetCollectionAddressCollections过滤...63

18.6.SNMP++Class返回的错误号...64

18.6.1.SnmpClass的错误消息成员函数...64

19.运行模式...65

19.1.MicrosoftWindows事件驱动系统的运作...65

19.2.OpenSystemsFoundation(OSF)X11Motif的运作...65

19.3.不以GUI为基础的应用的运作...65

20.状态&错误编号...67

21.错误状态值...68

22.SnmpClass例子...69

22.1.GettingaSingleMIBVariableExample.69

22.2.GettingMultipleMIBVariablesExample.69

22.3.SettingaSingleMIBVariableExample.71

22.4.SettingMultipleMIBVariablesExample.71

22.5.WalkingaMIBusingGet-NextExample.72

22.6.SendingaTrapExample.73

22.7.ReceivingTrapsExample.73

23.参考书目...75


SNMP++框架的对象模型(ObjectModelingTechnique)视图

1.介绍

目前有许多可以创建网络管理应用的SNMPAPI。大多数API都提供了一个很大的函数库,调用这些函数的程序员需要熟悉SNMP内部的工作原理和它的资源管理机制。这些API大多都是平台相关的,导致了SNMP代码也成了操作系统相关的或者网络系统平台有关的,难以移植。另一方面由于C++有丰富的、可复用的标准类库,用C++开发应用成了目前的主流,然而C++标准类库所缺少的正是一套封装好的处理网络管理的类。如果基于面向对象的方法来进行SNMP网络编程,可以提供以下诸多好处:易用、安全、可移植、能扩展。因此SNMP++灵活有效的解决了其他类似API执行和管理起来都很痛苦的问题。

1.1.什么是SNMP++

SNMP++是一套C++类的集合,它为网络管理应用的开发者提供了SNMP服务。SNMP++并非是现有的SNMP引擎的扩充或者封装。事实上为了效率和方便移植,它只用到了现有的SNMP库里面极少的一部分。SNMP++也不是要取代其他已有的SNMPAPI,比如WinSNMPSNMP++只是通过提供强大灵活的功能,降低管理和执行的复杂性,把面向对象的优点带到了网络编程中。

1.2.SNMP++的本质

1.2.1.简单易用的SNMP++

面向对象的SNMP编程应该是简单易用的。毕竟,SNMP原意就是简单网络管理协议SNMP++只是将简单还给SNMP!应用的开发者不需要关心SNMP的底层实现机制,因为面向对象的方法已经将SNMP内部机制封装、并隐藏好了。SNMP++的简单易用表现在以下方面:

1.2.1.1.为SNMP提供了简单易用的接口

使用SNMP++不需要精通SNMP,甚至不需要精通C++!因为SNMP++里面几乎没有C的指针,所以可以简单的通过API直接使用。

1.2.1.2.可以方便的迁移至SNMPv2

SNMP++的主要目标之一就是开发一套API,使得迁移至SNMPv2的过程中尽可能少地影响现有代码SnmpTargetclass使之成为了可能。

1.2.1.3.保留了对SNMP灵活的底层开发

这是为了方便那些不希望使用面向对象方法,而直接编写SNMP的底层机制的用户。虽然SNMP++快速而方便,但是有些时候程序员也许希望直接使用底层的SNMPAPI

1.2.1.4.鼓励程序员用功能强大的C++,不要因学得不够快而去指责它

使用SNMP++用户不需要精通C++。基本的SNMP的知识是必要的,但是实际上也需要对C++初步的理解。

1.2.2.编程安全的SNMP++

大多数SNMPAPI需要程序员去管理大量的资源。不恰当的装载或卸载这些资源,会导致内存崩溃或泄漏。SNMP++提供的安全机制,可以实现对这些资源的自动管理。SNMP++用户可以体验到自动管理资源与对话所带来的好处。SNMP++在编程上的安全突出表现在下面的领域:

1.2.2.1.为SNMP资源提供安全的管理

包括SNMP的结构、会话以及传输层的管理。SNMPclass被设计成所谓的抽象数据类型(ADT),隐藏了私有数据,而通过提供公有的成员函数来访问或修改这些隐藏了的实例变量。

1.2.2.2.提供查错、自动超时重发的机制

SNMP++用户不需要关心如何为不可靠的网络传输机制提供可靠性。可能出现的通信错误包括:数据包丢失、数据包重复以及反复提取数据包。SNMP++消除了所有这些问题出现的可能性,为用户提供了传输层的可靠性。

1.2.3.可移植的SNMP++

SNMP++的主要目的之一就是提供一套可移植的API,进而穿越各种操作系统(Os)、网络系统(NOS)以及网络管理平台。由于SNMP++隐藏了内部机制,所以从各个平台的角度来看SNMP++的公用接口都是一样的。使用SNMP++的程序员不需要为平台迁移去修改代码。另一个移植方面的问题是在多种协议上运行的能力。目前,SNMP++能运行在IP协议和IPX协议上,或者两者都可以。

1.2.4.可扩充的SNMP++

扩充不应该只是多一种选择,而是更深层次的。SNMP++不仅是可扩充,而且是很容易扩充。SNMP++的扩充囊括了对下列领域的支持:新的操作系统、网络系统、网络管理平台、网络协议、SNMPv2及其新特性。通过派生C++的类,SNMP++用户可以根据自己的喜好继承、重载。

1.2.4.1.重载SNMP++的基础类

应用的开发者可以通过派生出SNNP++的子类来提供所需的操作和属性,这正是面向对象的核心主题SNMP++的基础类被打造成通用的、没有包含任何具体的数据结构和操作。通过C++派生类以及重新定义虚函数,可以很容易的添加属性


2.一个介绍性的例子

在开始介绍SNMP++的各种特性之前,这里先举个简单的例子来展现它的强大和简单。该例子是从指定的代理端上获取SNMPMIB的系统描述符(SystemDescriptorobject)。包含了创建一个SNMP++会话、获取系统描述符,并打印显示出来的所需的所有代码。其中重发和超时机制已经被SNMP++自动管理了。以下属于SNMP++代码,采用粗体显示

2.1.一个简单的SNMP++例子

#include“snmp_pp.h”

#definesYSDESCR“1.3.6.1.2.1.1.1.0”//ObjectIDforSystemDescriptor

voidget_system_descriptor()

{

intstatus;//returnstatus

CTargetctarget((IpAddress)“10.4.8.5”);//SNMP++communitytarget

Vbvb(SYSDESCR);//SNMP++VariableBindingObject

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;}

//-------[InvokeaSNMP++Get]-------------------------------------------------------

pdu+=vb;//addthevariablebindingtothePDU

if((status=snmp.get(pdu,ctarget))!=SNMP_CLASS_SUCCESS)

cout<<snmp.error_msg(status);

else{

pdu.get_vb(vb,0);//extractthevariablebindingfromPDU

cout<<“SystemDescriptor=”<<vb.get_printable_value();}//printoutthevalue

};//Thatsall!

2.2.对介绍性例子的分析

真正属于SNMP++的语句就10代码。首先用代理端的IP地址建立一个CTarget对象;然后用MIB对象所定位的系统描述符创建一个变量绑定(Vb);接着就把这个Vb纳入一个Pdu对象;最后生成一个Snmp对象来执行SNMPget操作。一旦找到了所需的数据,对应的应答消息就被打印出来。另外,所有的处理错误代码也都包含在内了。


3.SNMP++特性

3.1.完整的一套SNMPC++

SNMP++是以一套C++类作为基石的。这些类是:对象描述符(Oid)类、变量绑定(Vb)类、协议数据单元(Pdu)类、Snmp类。并且,其他各种用抽象语法表示(ASN.1)来描述的管理信息结构(SMI),也被抽象成了简单的、面向对象的类型。

3.2.SNMP内存的自动管理

SNMP++的对象被实例化或销毁的时候,其相关的类可以自动管理着各种各样的SNMP结构和资源。这就使得应用的开发者不用再担心数据结构和资源的卸载,不然就得为防止内存的崩溃或者泄漏提供有效的保护措施。SNMP++的对象的实例化可以是静态的,也可以是动态的。静态的实例化可以在对象脱离它的作用域时卸载掉;动态分配则需要使用C++newdelete。在SNMP++内部,有许多被隐藏和保护在公用接口后面的SMI结构。所有的SMI结构都是在内部管理的,程序员不需要定义或管理SMI的结构和它的值。因为在SNMP++内绝大部分地方是不存在C的指针的。

3.3.简单易用的

由于隐藏并管理了所有SMI结构和它们的值,SNMP++的类使用起来即简单又安全。外部程序员无法破坏到隐藏和保护在作用域后面的小编。

3.4.强大灵活的

SNMP++提供了强大灵活的功能,降低了管理和执行的复杂性。每个SNMP++对象都通过建立一个会话来和一个代理端联系。即由一个SNMP++的对话类的实例,就能处理所有与特定代理端的连接。另外自动重发和超时控制的机制,为每个SNMP++对象都带来了可靠性。一个应用可能会包含许多SNMP++的对象的实例,每个实例都可能与相同或不同的代理端通话。有了这个功能强大的特性,网络管理程序就可以为每个管理单元建立起不同的会话。另一方面,就算单一的SNMP会话也可以解决问题。例如:一个应用可以通过一个SNMP++对象来处理图形统计,另一个SNMP++对象监控trap,也许还有第三个SNMP++对象用以浏览SNMPSNMP++自动并行处理了同一时刻来自不同SNMP++实例的请求。

3.5.可移植对象的

SNMP++的主体是可以移植的C++代码。其中只有SnmpClass的实现与不同的目标操作系统有关。如果你的程序中包含了SNMP++代码,那么导出这部分代码的时候,就可以不做任何修改

3.6.自动超时和重发机制

SNMP++提供了自动超时和重发机制,程序员不用去实现超时或重发机制的代码。重发机制是在SnmpTargetClass里面定义的,这就使得每一个目标(Target)都具有了它自己的超时/重发机制。

3.7.阻塞模式

SNMP++提供了阻塞方式。MS-Windows上的阻塞方式可以并发的阻塞从每个SNMP类的实例发出的请求。

3.8.异步的非阻塞模式

SNMP++还为应答提供了异步的非阻塞的方式。超时和重发机制同时支持阻塞和异步两种模式。

3.9.Notification、Trap的收发

SNMP++允许在多种传输层上(包括IPIPX)收发trap。而且SNMP++还允许使用非标准的IP端口和IPX套接口来收发trap

3.10.通过双效的API支持SNMPv1SNMPv2

SNMP++的设计可同时支持SNMPv1SNMPv2的使用。所有API的操作都被设计成了双效的,也即操作是SNMP版本无关的。通过使用SnmpTarget类,与SNMP的版本相关的操作被抽象出来了。

3.11.支持SNMPGet,InformTrap的操作

SNMP++完整的支持SNMP6种操作。这6SNMP++的成员函数使用相同的参数表,也都支持阻塞和非阻塞(异步)方式。

3.12.通过继承实现重定义

SNMP++是用C++实现的,所以允许程序员重载或重定义那些不适合他们的操作。举个例子:如果一个应用需要特定的Oid对象,那就需要建立一个OidClass的子类,用以继承所有Oid类的属性和操作,同时在派生类种加入新的属性和操作。


4.在Microsoftwindows系列操作系统上使用SNMP++

SNMP++已经在MS-Windows3.1,MS-WindowsForWorkGroups3.11,MS-WindowsNT3.51,andMS-Windows’95上实现了。

4.1.WinSNMPVersion1.1的使用

MS-Windows上可以用WinSNMPVersion1.1来运行SNMP++。这就使得其他用WinSNMP代码直接写的SNMP应用可以与SNMP++的应用兼容。注意,目前HPMS-Windows设备使用WinSNMP,其他设备不需要使用WinSNMP来进行ANS.1的编码和解码。但那些没有使用WinSNMP的设备也需要与WinSNMP的应用兼容,才能和SNMP++的应用兼容。

4.2.对IPIPX支持

可以通过一个WinSockcompliantstack,来实现对IP的操作。同时为了在IPX协议上运行,还需要兼容Novell网络的客户程序和驱动。目前SNMP++已经通过了在广泛多样的协议栈下的运行测试,这些协议栈包括FTPNetmanageLanWorkPlaceMS-WFWG3.11,以及WindowsNT

4.3.对NotificationTrap收发的支持

SNMP++包含了对WinSNMPtrap机制的支持。这同时包括trap的发送和收取。在接收trap的时候,还提供了过滤trap功能

4.4.与HPOpenViewforWindows兼容

已经有大量使用SNMP++创建的应用,实现了HPOpenViewforWindows的兼容。


5.在UNIX上使用SNMP++

5.1.统一的类的接口

用在UNIX设备上的SNMP++类的接口和MS-Windows是一样的。

5.2.Windows到UNIX的仿真与移植

通过编译、连接对应的SNMP++类,SNMP++就可以实现在UNIX上运行。SNMP++/UNIX的设计决定了它可以同时运行在原始的UNIX字符模式、X-Window模式,或者Windows-to-UNIX的仿真工具上。

5.3.与HPOpenViewforUNIX兼容

已经有大量使用SNMP++创建的应用,实现了与HPOpenViewforUNIX的兼容。


6.SNMPSyntaxClasses

SNMP++SNMPSyntax的对象模型(ObjectModelingTechnique)视图

SNMP++SNMPSyntaxclasse描绘了一个具有C++面向对象风格的视图。即用于描述SNMPSMIASN.1的数据类型视图。它包含了映射到对应的SMI类型的一组类的集合。而且为了方便使用,还引入了一些非SMI的类。SNMP++为这些SNMP数据类型提供了强大、简单易用的接口。下表概要地描述了各种SNMP++Syntaxclasses

SNMP++SyntaxClassName

ClassDescription

SMIorASN.1Counterpart

SnmpSyntax

ParentofallSyntaxclasses.

NoASN.1counterpart,usedforOOstructure.

Oid

Objectidentifierclass.

ASN.1ObjectIdentifier.

OctectStr

Octetstringclass.

ASN.1Octetstring.

Uint32

Unsigned32bitintegerclass.

SMIunsigned32bitinteger.

TimeTicks

TimeTicksclass.

SMItimeticks.

Counter32

32bitcounterclass.

SMI32bitcounter.

Gauge32

32bitgaugeclass.

SMI32bitgauge.

Int32

Signed32bitinteger.

SMI32bitsignedinteger.

Counter64

64bitcounterclass.

SMI64bitcounter.

Address

Abstractaddressclass.

NoASN.1counterpartusedforOOstructure.

IpAddress

IPaddressclass.

SMIIPaddress.

UdpAddress

UdpAddressclass

SMIIPaddresswithportspecification.

IpxAddress

IPXaddressclass.

NoASN.1orSMIcounterpart

IpxSockAddress

IPXAddressclasswithsocketnumber.

NoASN.1orSMIcounterpart

MacAddress

MACaddressclass.

SMIcounterpart

GenAddress

GenericAddress

NoASN.1orSMIcounterpart.


7.ObjectIdClass

SNMP++OidClass的对象模型(ObjectModelingTechnique)视图

7.1.对象标识符类

对象标识符类(Oid)封装了SMI的对象标识。信息管理库(MIB)中所定义的SMI的对象是一种在MIB中找到的数据元素的数据标识。与SMIOid相关的结构和函数,自然都是面向对象的。事实上OidclassC++Stringclass有许多共同之处。如果你熟悉C++Stringclass或者MFCCStringclass,那么你就会感觉Oidclass用起来很亲切、简单。Oidclass被设计成了快速有效的类;它可以定义和操作对象标识;不依赖现有的SNMPAPI,完全是可移植的;可以在任何ANSIC++编译器上进行编译。

7.2.OidClass的成员函数列表

OidClassMemberFunctions

说明

Constructors

Oid::Oid(void);

构造一个空的的Oid

Oid::Oid(constchar*dotted_string);

用带点的字符串构造新的Oid

Oid::Oid(constOid&oid);

用已有的Oid构造新的Oid

Oid::Oid(constunsignedlong*data,intlen);

通过一个指针和长度来构造一个新的Oid

Destructor

Oid::~Oid();

销毁一个Oid,释放所有的堆

OverloadedOperators

Oid&operator=(constchar*dotted_string);

一个带点的字符串付给一个Oid

Oid&operator=(constOid&oid);

一个Oid付给另一个Oid

intoperator==(constOid&lhs,constOid&rhs);

判断两个Oid是否相等

intoperator==(constOid&lhs,constchar*dotted_string);

判断一个Oid是否和一个带点的字符串相等

intoperator!=(constOid&lhs,constOid&rhs);

判断两个Oid是否不等

intoperator!=(constOid&lhs,constchar*dotted_string);

判断一个Oid是否和一个带点的字符串不相等

intoperator<(constOid&lhs,constOid&rhs);

判断一个Oid是否比另一个

intoperator<(constOid&lhs,constchar*dotted_string);

判断一个Oid是否比一个带点的字符串小

intoperator<=(constOid&lhs,constOid&rhs);

判断一个Oid是否小于等于一个

intoperator<=(constOid&lhs,constchar*dotted_string);

判断一个Oid是否小于等于一个带点的字符串

intoperator>(constOid&lhs,constOid&rhs);

判断一个Oid是否比另一个

intoperator>(constOid&lhs,constchar*dotted_string);

判断一个Oid是否比一个带点的字符串大

intoperator>=(constOid&lhs,constOid&rhs);

判断一个Oid是否大于等于一个

intoperator>=(constOid&lhs,constchar*dotted_string);

判断一个Oid是否大于等于一个带点的字符串

Oid&operator+=(constchar*dotted_string);

一个带点的字符串加到一个Oid后面

Oid&operator+=(constunsignedlongi);

一个整数加到一个带点的Oid字符串后面

Oid&operator+=(constOid&oid);

一个Oid加到另一个Oid后面

unsignedlong&operator[](intposition);

访问Oid一个独立子单元

OutputMemberFunctions

char*get_printable(constunsignedintn);

返回一个Oidn个带点格式的子单元

char*get_printable(constunsignedlongs,constunsignedlongn);

返回从s开始,以点号分割的n个子单元

char*get_printable();

返回以点号分割的Oid字符串

operatorchar*();

同上

MiscellaneousMemberFunctions

set_data(constunsignedlong*data,constunsignedlongn);

用指针和长度来设置一个Oid

unsignedlonglen();

返回Oid中子单元的个数(长度)

trim(constunsignedlongn=1);

删除Oid最右边的n个子单元,删除1

nCompare(constunsignedlongn,constOid&oid);

从左至右比较Oid的前n个子单元

RnCompare(constunsignedlongn,constOid&oid);

从右至左比较Oid的后n个子单元

intvalid();

返回Oid的有效性

7.3.一些OidClass的例子

下面的例子展示了OidClass的不同用法OidClass不需要依赖其他库和模块。下列代码ANSI/ISOC++上编译通过

#include“oid.h”

voidoid_example()

{

//constructanOidwithadottedstringandprintitout

Oido1("1.2.3.4.5.6.7.8.9.1");

cout<<“o1=“<<o1.get_printable();

//constructanOidwithanotherOidandprintitout

Oido2(o1);

cout<<“o2=”<<o2.get_printable();

//trimo2’slastvalueandprintitout

o2.trim(1);

cout<<“o2=”<<o2.get_printable();

//adda2valuetotheendofo2andprintitout

o2+=2;

cout<<“o2=”<<o2.get_printable();

//createanewOid,o3

Oido3;

//assigno3avalueandprintitout

o3="1.2.3.4.5.6.7.8.9.3";

cout<<“o3=”<<o3.get_printable();

//createo4

Oido4;

//assigno4o1’svalue

o4=o1;

//trimoffo4by1

o4.trim(1);

//concata4ontoo4andprintitout

o4+=”.4”;

cout<<“o4=”<<o4.get_printable();

//makeo5fromo1andprintitout

Oido5(o1);

cout<<“o5=”<<o5.get_printable();

//comparetwonotequaloids

if(o1==o2)cout<<"O1EQUALSO2";

elsecout<<"o1notequaltoo2";

//printoutapieceofo1

cout<<"strval(3)ofO1=“<<o1.get_printable(3);

//printoutapieceofo1

cout<<"strval(1,3)ofO1=“<<o1.get_printable(1,3);

//seto1'slastsubid

o1[o1.len()-1]=49;

cout<<"O1modified=“<<o1.get_printable();

//seto1's3rdsubid

o1[2]=49;

cout<<"O1modified=“<<o1.get_printable();

//getthelastsubidof02

cout<<"lastofo2=“<<o2[o2.len()-1];

//getthe3rdsubidof02

cout<<"3rdofo2=“<<o2[2];

//ncompare

if(o1.nCompare(3,o2))

cout<<"nCompareo1,o2,3==";

else

cout<<"nCompareo1,3!=";

//makeanarrayofoids

Oidoids[30];intw;

for(w=0;w<30;w++)

{

oids[w]="300.301.302.303.304.305.306.307";

oids[w]+=(w+1);

}

for(w=0;w<25;w++)

{

sprintf(msg,"Oids[%d]=%s",w,oids[w].get_printable());

printf(“%s”,msg,strlen(msg));

}

}


8.OctetStrClass

SNMP++OctetStrClass的对象模型(ObjectModelingTechnique)视图

8.1.八位字节类

通过SNMP++Octetclass,可以简单且安全地操作SMI8位字节。有了Octetclass,就不需要通过内部指针和长度来操作8位字节了。使用SNMP++Octetclass来实例化、操作、销毁一个8位字节对象是很简单的,不用担心如何管理内存以及内存是否会泄漏。与ANSIC++stringclass类似,OctetStrclass可以通过多种方法构造8位字节,还可以对它们进行赋值操作,与其他SNMP++classes一起使用。

8.2.OctetStrClass的成员函数列表

OctetStrClassMemberFunctions

说明

Constructors

OctetStr::OctetStr(void);

构造一个空的OctetStr

OctetStr::OctetStr(constchar*string);

一个没有结束符的字符串构造OctetStr

OctetStr::OctetStr(constunsignedchar*s,unsignedlonginti);

通过一个指针和长度来构造OctetStr

OctetStr::OctetStr(constOctetStr&octet);

用已有的OctetStr构造新的OctetStr

Destructor

OctetStr::~Octetstr();

销毁一个OctetStr

OverloadedOperators

OctetStr&operator=(constchar*string);

一个没有结束符的字符串付给一个OctetStr

OctetStr&operator=(constOctetStr&octet);

一个OctetStr付给另一个OctetStr

intoperator==(constOctetStr&lhs,constOctetStr&rhs);

判断两个OctetStr对象是否相等

intoperator==(constOctetStr&lhs,constchar*string);

判断OctetStr是否和一个char*字符串相等

intoperator!=(constOctetStr&lhs,constOctetStr&rhs);

判断两个OctetStr对象是否不相等

intoperator!=(constOctetStr&lhs,constchar*string);

判断OctetStr是否和一个char*字符串不相等

intoperator<(constOctetStr&lhs,constOctetStr&rhs);

判断一个OctetStr是否比另一个

intoperator<(constOctetStr&lhs,constchar*string);

判断一个OctetStr是否比另一个char*字符串小

intoperator<=(constOctetStr&lhs,constOctetStr&rhs);

判断一个OctetStr是否小于等于一个

intoperator<=(constOctetStr&lhs,constchar*string);

判断一个OctetStr是否小于等于一个char*的字符串

intoperator>(constOctetStr&lhs,constOctetStr&rhs);

判断一个OctetStr是否比另一个

intoperator>(constOctetStr&lhs,constchar*string);

TestifoneOctetStrisgreaterthanachar*.

判断一个OctetStr是否比一个char*的字符串大

intoperator>=(constOctetStr&lhs,constOctetStr&rhs);

判断一个OctetStr是否大于等于一个

intoperator>=(constOctetStr&lhs,constchar*);

判断一个OctetStr是否大于等于一个char*的字符串

OctetStr&operator+=(constchar*string);

一个OctetStr后面连接一个字符串

OctetStr&operator+=(constunsignedcharc);

一个OctetStr后面连接一个单字符

OctetStr&operator+=(constOctetStr&octetstr);

将两个OctetStr连接在一起

unsignedchar&operator[](intpositioni);

用数组的形式来访问一个OctetStr

Miscellaneous

voidset_data(constunsignedchar*s,unsignedlongl);

用指针和长度来设置一个OctetStr

intnCompare(constunsignedlongn,constOctetStr&o);

与另一个OctetStr比较前n个元素

unsignedlonglen();

返回一个OctetStr的长度

intvalid();

返回一个OctetStr的有效性

unsignedchar*data();

返回一个指向内部数据的指针

char*get_printable();

格式化输出,如果不是ASCII则按16进制处理

char*get_printable_hex();

16进制格式,进行格式化输出

8.3.注意

输出一个OctetStr对象时,如果该8位字节所包含的字符不是ASCII码,对成员函数char*或者get_printable()调用,就会自动转换成对成员函数get_printable_hex()调用。这就使得使用者只需要简单地使用成员函数char*get_printable()来进行输出。而成员函数get_printable_hex()是专门用来把OctetStr16进制格式输出的。

8.4.一些OctetStrClass的例子

//OctetClassExamples

#include“octet.h”

voidoctet_example()

{

OctetStroctet1;//createaninvalidun-initializedoctetobject

OctetStroctet2(“RedHookExtraBitterale”);//createanoctetwithastring

OctetStroctet3(octet2);//createanoctetwithanotheroctet

unsignedcharraw_data[50];//createsomerawdata

OctetStroctet4(raw_data,50);//createanOctetStrusingunsignedchardata

octet1=“SierraNevadaPaleAle”;//assignoneoctettoanother

cout<<octet1.get_printable();//showoctet1asanullterminatedstring

cout<<octet4.get_printable_hex();//showoctet4asahexstring

cout<<(char*)octet1;//sameasget_printable()

if(octet1==octet2)//comparetwooctets

cout<<“octet1isequaltooctet2”;

octet2+=“WinterFestAle”;//concatastringtoanOctet

if(octet2>=octet3)

cout<<“octet2greaterthanorequaltooctet2”;

octet2[4]=‘b’;//modifyanelementofanOctetStrusing[]’s

cout<<octet.len();//printoutthelengthofanOctetStr

unsignedcharraw_data[100];

octet1.set_data(raw_data,100);//setthedataofantounsignedchardata

//getthevalidityofanOctetStr

cout<<(octet1.valid())?“Octet1isvalid”:“Octet1isInvalid”;

};//endoctetexample


9.TimeTicksClass

SNMP++TimeTicksClass的对象模型(ObjectModelingTechnique)视图


9.1.时间戳类

SNMP++TimeTicksClass为使用SMI中的timeticks带来了方便。SMI的时间戳被定义成了一种存放无符号长整形的存储单元。为了成为无符号长整形,SMItimeticks被加工成了一种特殊的类型。因此SNMP++TimeTicks类具有无符号长整形的所有功能属性,但同时又是一个独立的类。对无符号长整形的任何操作,拿到TimeTicks的对象上一样有效。TimeTicksclass与其他SNMP++的类,比如Vbclass交互的时候,还可以有些额外的操作:在使用Vbclass的时候,TimeTicks的对象可以被置入Vb对象(用Vb::set),也从Vb对象中取出(用Vb::get)。也即,对于SMItimeticks,开发者可以像对无符号长整形一样来操作,并且还提供了一对一的映射关系。

9.2.TimeTicksClass的成员函数列表

TimeTicksClassMemberFunctions

说明

Constructors

TimeTicks::TimeTicks(void);

构造一个空的TimeTicks对象

TimeTicks::TimeTicks(constunsignedlongi);

一个无符号长整形来构造一个TimeTicks对象

TimeTicks:;TimeTicks(constTimeTicks&t);

一个已有的TimeTicks对象来构造一个新的

Destructor

TimeTicks::~TimeTicks();

销毁一个TimeTicks对象

OverloadedOperators

TimeTicks&operator=(constTimeTicks&t);

重载赋值操作符

char*get_printable();

格式化输出,格式为:DDDays,HH:MM:SS.hh

operatorunsignedlong();

TimeTicks转换为无符号长整形

9.3.注意

TimeTicks对象用TimeTicks::get_printable()输出时,其值自动被格式化为“DDdays,HH:MM:SS.hh”。其中DD代表天,HH代表小时(24时制的),MM代表分钟,SS是秒钟,hh则是百分之几秒。

9.4.一些TimeTicksClass的例子

//TimeTicksExamples

#include“timetick.h”

voidtimeticks_example()

{

TimeTickstt;//createanun-initializedtimeticksinstance

TimeTickstt1((unsignedlong)57);//createatimeticksusinganumber

TimeTickstt2(tt1);//createatimeticksusinganotherinstance

tt=192;//overloadedassignmenttoanumber

tt2=tt;//overloadedassignmenttoanothertimeticks

cout<<tt.get_printable();//printoutinDDdays,HH:MM:SS.hh

cout<<(unsignedlong)tt;//printoutunsignedlongintvalue

};//endtimeticksexample


10.Counter32Class

SNMP++Counter32Class的对象模型(ObjectModelingTechnique)视图

10.1.32位计数器类

当需要用到SMI中的32位计数器时,SNMP++Counter32Class为之带来了方便。SMI的计数器被定义成了一种存放无符号长整形的存储单元。为了成为无符号长整形,SMIcounters被加工成了一种特殊的类型。因此SNMP++Counter32类具有无符号长整形的所有功能属性,但同时又是一个独立的类。对无符号长整形的任何操作,拿到Counter32的对象上一样有效。Counter32class与其他SNMP++的类,比如Vbclass交互的时候,还可以有些额外的操作:在使用Vbclass的时候,Counter32的对象可以被置入Vb对象(用Vb::set),也从Vb对象中取出(用Vb::get)。也即,对于SMIcounter,开发者可以像对无符号长整形一样来操作,并且还提供了一对一的映射关系。

10.2.Counter32Class的成员函数列表

Counter32ClassMemberFunctions

说明

Constructors

Counter32::Counter32(void);

构造一个空的Counter32对象

Counter32::Counter32(constunsignedlongi);

一个无符号长整形来构造一个Counter32对象

Counter32::Counter32(constCounter32&c);

一个已有的Counter32对象来构造一个新的

Destructor

Counter32::~Counter32();

销毁一个TimeTicks对象

OverloadedOperators

Counter32&operator=(constCounter32&c);

重载赋值操作符

char*get_printable();

格式化输出Counter32对象

operatorunsignedlong();

Counter32转换为无符号长整形

10.3.一些Counter32Class的例子

//CounterExamples

#include“counter.h”

voidcounter_example()

{

Counter32ctr;//createanun-initializedcounterinstance

Counter32ctr1((unsignedlong)57);//createacounterusinganumber

Counter32ctr2(ctr1);//createacounterusinganotherinstance

ctr=192;//overloadedassignmenttoanumber

ctr1=ctr;//overloadedassignmenttoanothercounter

cout<<(unsignedlong)ctr;//behavelikeanunsignedlongint

};//endcounterexample


11.Gauge32Class

SNMP++Gauge32Class的对象模型(ObjectModelingTechnique)视图


11.1.容量类

SNMP++Gauge32Class为使用SMI中的timeticks带来了方便。SMI的容量被定义成了一种存放无符号长整形的存储单元。为了成为无符号长整形,SMIgauges被加工成了一种特殊的类型。因此SNMP++Gauge32类具有无符号长整形的所有功能属性,但同时又是一个独立的类。对无符号长整形的任何操作,拿到Gauge32的对象上一样有效。Gauge32class与其他SNMP++的类,比如Vbclass交互的时候,还可以有些额外的操作:在使用Vbclass的时候,TimeTicks的对象可以被置入Vb对象(用Vb::set),也从Vb对象中取出(用Vb::get)。也即,对于SMIgauge,开发者可以像对无符号长整形一样来操作,并且还提供了一对一的映射关系。

11.2.Gauge32Class的成员函数列表

Gauge32ClassMemberFunctions

说明

Constructors

Gauge32::Gauge32(void);

构造一个空的Gauge32对象

Gauge32::Gauge32(constunsignedlongi);

一个无符号长整形来构造一个Gauge32对象

Gauge32::Gauge32(constGauge32&g);

一个已有的Gauge32对象来构造一个新的

Destructor

Gauge32::Gauge32();

销毁一个Gauge32对象

OverloadedOperators

Gauge32&operator=(constGauge32&g);

重载赋值操作符

char*get_printable();

格式化输出Gauge32对象

operatorunsignedlong();

Gauge32转换为无符号长整形

11.3.一些Gauge32的例子

//GaugeExamples

#include“gauge.h”

voidgauge_example()

{

Gauge32gge;//createanun-initializedGaugeinstance

Gauge32gge1((unsignedlong)57);//createaGaugeusinganumber

Gauge32ctr2(ctr1);//createaGaugeusinganotherinstance

gge=192;//overloadedassignmenttoanumber

gge1=gge;//overloadedassignmenttoanothercounter

cout<<(unsignedlong)gge;//behavelikeanunsignedlongint

};//endgaugeexample


12.Counter64Class

SNMP++Counter64Class的对象模型(ObjectModelingTechnique)视图


12.1.64位计数器类

SNMP++64bitcounterclass实现了SMI64bitcounters64位计数器是在SNMPv2中定义的一种变量,所以在SNMPv1中并不存在这MIB变量。64bitcounters由两个无符号长整形(一高位、一低位)组成,Counter64class很好的实现了它。因为Counter64class提供了加减乘除操作符的重载,所以它使用起来感觉很自然。

12.2.Counter64Class的成员函数列表

Counter64ClassMemberFunctions

说明

Constructors

Counter64::Counter64(void);

构造一个空的Counter64对象

Counter64::Counter64(constunsignedlonghi,constunsignedlonglow);

用两个无符号长整形来构造一个Counter64对象

Counter64::Counter64(constCounter64&ctr64);

拷贝构造函数

Counter64::Counter64(constunsignedlongul);

一个无符号长整形来构造一个Counter64对象

Destructor

Counter64::~Counter64();

销毁一个Counter64对象

OverloadedOperators

Counter64&operator=(constCounter64&ctr64);

一个Counter64对象付给另一个

Counter64&operator=(constunsignedlongi);

一个无符号长整形设置Counter64对象的低位,同时清除了它的高位

Counter64operator+(constCounter64&ctr64);

两个Counter64对象相加

Counter64operator-(constCounter64&ctr64);

两个Counter64对象相减

Counter64operator*(constCounter64&ctr64);

两个Counter64对象相乘

Counter64operator/(constCounter64&ctr64);

两个Counter64对象相除

intoperator==(Counter64&lhs,Counter64&rhs);

判断两个Counter64对象是否相等

intoperator!=(Counter64&lhs,Counter64&rhs);

判断两个Counter64对象是否不相等

intoperator<(Counter64&lhs,Counter64&rhs);

判断一个Counter64是否比另一个

intoperator<=(Counter64&lhs,Counter64&rhs);

判断一个Counter64是否小于等于一个

intoperator>(Counter64&lhs,Counter64&rhs);

判断一个Counter64是否比另一个

intoperator>=(Counter64&lhs,Counter64&rhs);

判断一个Counter64是否大于等于一个

MemberFunctions

unsignedlonghigh();

返回Counter64对象的高位

unsignedlonglow();

返回Counter64对象的低位

voidset_high();

设置Counter64对象的高位

voidset_low();

设置Counter64对象的低位

12.3.一些的Counter64Class例子

//Counter64examples

#include“ctr64.h”

voidcounter64_example()

{

Counter64c64;//instantiatea64bitcounterobjectwithnoparms

Counter64my_c64(100,100);//instantiatea64bitcounterwithahiandlowvalue

Counter64your_c64(my_c64);//instantiatea64counterusinganother64bitcounter

cout<<my_c64.high();//printoutthehighportionofthec64

cout<<my_c64.low();//printoutthelowportionofthec64

c64=my_c64+your_c64;//overloadedaddition

c64=my_c64*your_c64;//overloadedmultiplication

c64=my_c64/your_c64;//overloadeddivision

c64=my_c64-your_c64;//overloadedsubtraction

if(c64==my_c64)//overloadedequivalencetest

cout<<“c64equalsmy_c64\n”;

if(c64!=my_c64)//overloadednotequaltest

cout<<“c64notequaltomy_c64\n”;

if(c64<my_c64)//overloadedlessthan

cout<<“c64lessthanmy_c64\n”;

};//endCounter64example


13.AddressClass

SNMP++AddressClass的对象模型(ObjectModelingTechnique)视图

13.1.什么是网络地址类?

网络地址类是一组C++类的集合,它提供了简单、安全、可移植、高效地使用网络地址的方法。许多网络管理应用需要通过网络地址来访问和管理设备,包括地址的确认、更改,以及用户接口的分配。Addressclass不但管理了所有指定的网络地址的内部细节,而且还通过封装和隐藏其内部机制,让得到解放的开发应用的程序员可以专注于解决实际问题。开发Addressclass的动机来源于95InteropSNMP++Birds-of-A-Feather(BOF)上的讨论以及与Hewlett-PackardOpenView程序员的交流。

13.2.为什么要使用网络地址类?

地址类提供了以下好处:自动内存管理、地址确认、移植到任何C++环境、简单易用,及可扩充性。目前的Addressclass4个子类组成:IpAddressClass,IpxAddressClass,MacAddressclassGenAddressclass。将来也许会有其他的子类加入,比如IPNextGeneration(IPng)

13.3.Addressclass

所有地址类都派生自同一个抽象基类:Addressclass。它是一个抽象类,即这个类不会产生实例对象。Addressclass通过使用虚成员函数,提供了公用接口。也就是说可以使用公用接口调用各个不同地址类的函数。这样的结果是:当需要修改使用了地址类的模块时,需要改动的代码就很少了。

13.4.AddressClasses及其接口

作为基类的AddressClasses一个抽象类,它囊括了所有子类的通用操作。也即包含了以下统一的接口:构造、访问、修改地址。


AddressClassMemberFunctions

说明

IpAddressClassConstructors

IpAddress::IpAddress(void);

构造一个空的IpAddress对象

IpAddress::IpAddress(constchar*string);

一个字符串构造一个IpAddress,当需要时一般用到DNS

IpAddress::IpAddress(constIpAddress&ipa);

拷贝构造函数

IPAddressMemberFunctions

char*friendly_name(int&status);

DNS的名字看起来更友好

UdpAddressConstructors

UdpAddress::UdpAddress(void);

构造一个无效的UdpAddress对象

UdpAddress::UdpAddress(constchar*string);

一个字符串构造一个UdpAddress

UdpAddress::UdpAddress(constUdpAddress&udpa);

一个已有的UdpAddress来构造另一个

UdpAddressMemberFunctions

voidUdpAddress:set_port(constunsignedintp);

设置UdpAddress对象的端口号

unsignedintUdpAddress::get_port();

获取UdpAddress对象的端口号

IpxAddressClassConstructors

IpxAddress::IpxAddress(void);

构造一个空的IPX地址

IpxAddress::IpxAddress(constchar*string);

一个字符串构造一个IPX地址

IpxAddress::IpxAddress(constIpxAddress&ipxa);

拷贝构造函数

IpxSockAddressConstuctors

IpxSockAddress::IpxSockAddress(void);

构造一个空的IpxSockAddress对象

IpxSockAddress::IpxSockAddress(constchar*string);

一个字符串构造一个IpxSockAddress

IpxSockAddress::IpxSockAddress(constIpxSockAddress&ipxs);

一个已有的IpxSockAddress来构造另一个

IpxSockAddressMemberFunctions

IpxSockAddress::set_socket(constunsignedints);

一个IpxSockAddress获得套接

unsignedintIpxSocketAddress::get_socket();

设置一个IpxSockAddress套接

MacAddressConstructors

MacAddress::MacAddress(void);

构造一个空的MacAddress对象

MacAddress::MacAddress(constchar*string);

一个字符串构造一个MacAddress

MacAddress::MacAddress(constMacAddress&mac);

拷贝构造函数

GenAddressConstructors

GenAddress::GenAddress(void);

构造一个无效的GenAddress对象

GenAddress::GenAddress(constchar*addr);

一个字符串构造一个GenAddress

GenAddress::GenAddress(constGenAddress&addr);

拷贝构造函数

CommonMemberFunctions,applicabletoallAddressclasses

intoperator==(constAddress&lhs,constAddressrhs);

判断两个地址是否相等

intoperator!=(constAddress&lhs,constAddress&rhs);

判断两个地址是否不相等

intoperator>(constAddress&lhs,constAddress&rhs);

判断一个地址是否大于另一个

intoperator>=(constAddress&lhs,constAddress&rhs);

判断一个地址是否大于等于另一个

intoperator<(constAddress&lhs,constAddress&rhs);

判断一个地址是否小于另一个

intoperator<=(constAddress&lhs,constAddress&rhs);

判断一个地址是否小于等于另一个

intoperator==(constAddress&lhs,cosntchar*inaddr);

判断一个地址是否等于一个字符串

intoperator>(constAddress&lhs,constchar*inaddr);

判断一个地址是否大于一个字符串

intoperator<(constAddress&lhs,constchar*inaddr);

判断一个地址是否小于一个字符串

virtualintvalid();

判断一个地址的有效性

unsignedchar&operator[](intposition);

允许通过数组的下标操作符来访问一个地址

char*get_printable();

返回格式化输出的地址

13.5.IpAddressClass的特点

IpAddressClass可以通过调用成员函数Address::get_printable()自动DNS显示出来。如果没有激活DNS或者无法识别地址,则返回以点号分割的字符。另一方面,一个IpAddress可以用一个友好的名字(字符串,而非以点号分割的数字)来构造,这样构造函数就可以激活DNS显示。如果这个名字没被找到,那么该地址也就是无效的。这个强大的功能允许你在对外表现时,使用友好的名字方式。

13.6.GenAddress的特点

GenAddressclass允许创建和使用通用的地址,即GenAddress拥有其他地址类(IpAddress,IpxAddressMacAddress)的操作和属性,所以你可以使用GenAddress来操作任何地址。GenAddressclass的构造函数允许用任何字符串来建立一个地址。构造函数通过匹配的字符串以及加载在GenAddress上的属性与操作,决定其地址的具体类型。这样就解放了程序员,因为面对不一样的地址,程序员不用再专门写代码来处理了。

GenAddressExamples

GenAddressaddress1(“10.4.8.5”);//makeanIPGenAddress

GenAddressaddress2(“01020304-10111213141516”);//makeanIPXGenAddress

GenAddressaddress3(“01:02:03:04:05:06”);//makeaMACGenAddress

cout<<address3.get_printable();//printouttheGenAddress

if(!address1.valid())//checkvalidity

cout<<“address1!valid”;

13.7.AddressClass的有效性

所有地址类都支持成员函数::valid(),它可以返回指定地址对象的有效性。有效性是在构造或给一个地址对象赋值时决定的。只有在赋值之后,成员函数::valid()才可以被用来判断其有效性。

AddressClassValidationExamples

MacAddressmac;

mac=“01.010a0d”;//invalidMACaddress

printf(“%s”,(mac.valid()?“Valid”:”Invalid”));

13.8.UdpAddresses和IpxSockAddresses

大多数时候,SNMP++用户会使用认的端口号和套接字来进行SNMP操作。就IP协议而言,161端口一般用来作为代理的目标端口,162端口一般用作trapNotification的接收端口。有些时候需要改变指定的端口号和套接字,UdpAddressclassIpxSockAddressclass就允许定义端口和套接字的信息。

13.8.1.用UdpAddresses发送请求

当向一个使用非标准认端口的代理端发送请求信息时,就需要用到UdpAddressesclass了。UdpAddressesclass提供了两个成员函数分别来设置和获取自定义的端口信息。用一个加载了UdpAddresses的目标来发送请求,就可以实现SNMP++自定义端口的使用。

13.8.2.用IpxSockAddresses发送请求

当向一个使用非标准IPX套接字的代理端发送请求信息时,就需要用到IpxSockAddressesclass了。IpxSockAddresses提供了两个成员函数分别来设置和获取自定义IPX套接字信息。用一个加载了IpxSockAddress的目标来发送请求,就可以实现SNMP++自定义套接字的使用。

13.8.3.用UdpAddressIpxSockAddress接收Notification

UdpAddressIpxSockAddress还可以通过指定需要修改的端口和套接字来接收notification。即允许应用通过非标准的端口和套接字来接收trapinform

13.9.有效的地址格式

目前的有效地址格式定义如下:

ValidIpformatBNFGrammarXXX.XXX.XXX.XXX

ip-address:ip-tokenDOTip-tokenDOTip-tokenDOTip-token

DOT:‘.’

ip-token:[0-255]

ValidIPXformatBNFGrammarXXXXXXXX:XXXXXXXXXXXX

ipx-address:net-idSEParaTORmac-id

SEParaTOR:‘‘|‘:’|‘-’|‘.’

net_id:1{byte-token}4

mac-id:1{byte-token}6

byte-token:1{byte}2

byte:[0-9|a-f|A-F]

ValidMACformatBNFGrammarXX:XX:XX:XX:XX:XX

mac-id:byte_tokencolonbyte_tokencolonbyte_tokencolonbyte_tokencolonbyte_token

byte-token:1{byte}2

byte:[0-9|a-f|A-F]

colon:‘:’

13.10.AddressClass例子

//addressclassexamples

#include“address.h”

voidaddress_examples()

{

//--------------[IPAddressconstruction]------------------------------------------------------

IpAddressip1();//makesaninvalidIpAddressobject

IpAddressip2(“10.4.8.5”);//makesaIpAddressverifiesdottedformat

IpAddressip3(ip2);//makesanIpAddressusinganotherIpAddress

IpAddressip4(“trout.rose.hp.com”);//makesanIpAddressdoesDNSonstring

//-------------[IPXAddressconstruction]-----------------------------------------------------

IpxAddressipx1();//makesaninvalidIPXaddress

IpxAddressipx2(”);//makesandverifiesanIPXaddress

IpxAddressipx3(ipx2);//makesanIPXfromanotherIPX

//--------------[MACAddressconstruction]-----------------------------------------------------

MacAddressmac1();//makesaninvalidMACaddress

MacAddressmac2(“08:09:12:34:52:12”);//makesandverifiesaMACaddress

MacAddressmac3(mac2);//makesaMACfromanotherMAC

//---------------[GenAddressConstruction]-----------------------------------------------------

GenAddressaddr1(“10.4.8.5”);

GenAddressaddr2(“01020304:050607080900”);

//--------------[printingaddresses]----------------------------------------------------------------

cout<<(char*)ip2;

cout<<(char*)ipx2;

cout<<(char*)mac2;

//---------------[assigningAddresses]------------------------------------------------------------

ip1=“15.29.33.10”;

ipx1=“00000001-080912345212”;

mac1=“08:09:12:34:52:12”;

//--------------[comparingAddresses]----------------------------------------------------------

if(ip1==ip2)

cout<<“ip1==ip2”;

if(ipx1!=ipx2)

cout<<“ipx1!=ipx2”;

if(mac1<=mac2)

cout<<“mac1<mac2”;

//---------------[modifyinganaddress]-----------------------------------------------------------

mac1[4]=15;

cout<<mac2[2];

};//endaddressexamples


14.TheVariableBindingClass

SNMP++VariableBinding(Vb)Class的对象模型(ObjectModelingTechnique)视图

VariableBinding(Vb)classSNMP“绑定变量的封装。一个绑定变量是由SNMPobjectID及其SMIvalue组合而成的。用面向对象的概念来看,这只是一个简单的关联关系:一个Vb对象含有一个Oid对象及其SMIvalueVbclass允许应用的开发者实例化Vb对象,然后为其分配Oid部分(用Vb::set_value()),并分配value部分(用Vb::get_value())。相反的,Oidvalue部分可以通过成员函数Vb::get_oid()Vb::get_value()提取出来。通过重载了的公有成员函数Vb::set_value()Vb::get_value(),可以把不同的SMIvalue针对绑定变量进行设置取出绑定变量表SNMP++中表现为Vb对象的数组。所有的SMI类型都与VbClass兼容。Vbclass隐藏了所有内部数据。使用者不需要知道SMIvalue的类型,Oid的内部表示方法,以及其他SNMP相关的结构。如果使用的是标准ANSIC++编译器,Vbclass是完全可移植的。

14.1.VariableBindingClass成员函数列表

VariableBindingClassMemberFunctions

说明

Constructors

Vb(void);

构造一个空的Vb对象

Vb(constOid&oid);

Oid部分构造一个Vb

Vb(constVb&vb);

拷贝构造函数

Destructor

~Vb();

销毁一个Vb,释放所有的资源

Setoid/Getoid

voidset_oid(constOid&oid);

设置一个VbOid部分

voidget_oid(Oid&oid)const;

获得Oid部分

SetValue

voidset_value(constSMIValue&val);

设置任一SmiValue

voidset_value(constinti);

设置一整形value

voidset_value(constlonginti);

设置一长整形value

voidset_value(constunsignedlonginti);

设置一无符号长整形value

voidset_value(constcharWINFAR*ptr);

设置一有结束标志符的字符串value

GetValue

intget_value(SMIValue&val);

获得任一SmiValue

intget_value(int&i);

获得一整形value

intget_value(longint&i);

获得一长整形value

intget_value(unsignedlongint&i);

获得一无符号长整形value

intget_value(unsignedcharWINFAR*ptr,

unsignedlong&len);

获得一无符号字符数组,返回数据及其长度

intget_value(unsignedcharWINFAR*ptr,

unsignedlong&len,

unsignedlongmaxlen);

获得一指定长度的无符号字符数组,指定长度不超过最大长度。

intget_value(charWINFAR*ptr);

获得一有结束标志符的字符串

Miscellaneous

SmiuiNT32get_Syntax();

返回SMI描述

char*get_printable_value();

返回格式化value

char*get_printable_oid();

返回格式化Oid部分

voidset_null();

Vb对象设置一个value

intvalid();

返回一个Vb的有效性

OverloadedOperators

Vb&operator=(constVb&vb);

一个Vb付给另一个

14.2.VbClass的公有成员函数

Vbclass提供了许多公有成员函数来访问和修改Vb对象。

//AVbobjectmaybeconstructedwithnoarguments.Inthiscase,theOidand

//valueportionsmustbesetwithsubsequentmemberfunctioncalls.

//constructorwithnoarguments

//makesanVb,un-initialized

Vb::Vb(void);

14.2.1.VbClass的构造和析构函数

Vb对象可以用一个Oid对象作为构造函数的参数来构造,即把Vb对象的Oid部分初始化为以参数方式传进来的OidVb对象生成一个传进来的Oid的拷贝,所以程序员不用担心Oid参数的执行期问题。

//constructortoinitializetheOid

//makesaVbwithOidportioninitialized

Vb::Vb(constOidoid);

Vb对象的析构函数释放了所有占用过的内存和资源。对于定义的静态对象,析构函数是在对象作用域结束时自动调用的。动态分配的实例对象需要用delete来析构。

//destructor

//iftheVbhasaOidoranoctetstringthen

//theassociatedmemoryneedstobefreed

Vb::~Vb();

14.2.2.VbClass的Getoid/Setoid成员函数

成员函数Getoid/Setoid允许获取/设置Vb对象的Oid部分。当SNMP发出gets或者sets操作的时候,变量的指定是通过Vb::set_oid(Oidoid).设置VbOid值来的。相反,Oid部分可以通过成员函数Vb::get_oid(Oid&oid)获取。成员函数get_oidSNMPgetnext操作中的非常有用。

Vb对象的Oid部分可以用一个已存在的Oid对象来设置

//setvalueOidonlywithanotherOid

voidVb::set_oid(constOid&oid);

Oid部分可以通过提供一个目标Oid对象来检索。这将销毁原先的Oid对象的值。

//getoidportion

voidVb::get_oid(Oid&oid);

14.2.3.VbClass的GetValue/SetValue成员函数

成员函数get_valueset_value允许获取或设置Vb对象的value部分。这些成员函数通过重载支持对不同类型的获取和设置。隐藏了获取或设置Vb的内部机制,管理了所有内存的分配和释放。这样,程序员就不用担心SMI-value的结构以及它们的管理。通常在SNMP执行了get后,用成员函数getvalue获取Vb对象的value。如果希望在SNMP执行set操作时设置Vbvalue的话,成员函数setvalue就有用了。如果获取valueVb所包含的不匹配,则成员函数get_value返回-1

Vb对象设置一整形value,作为SMIINT的映射。

//setthevaluewithanint

voidVb::set_value(constinti);

Vb对象设置一长整形value,作为SMIINT32的映射。

//setthevaluewithalongsignedint

voidVb::set_value(constlonginti);

Vb对象设置一无符号长整形value,作为SMIUNIT32的映射。

//setthevaluewithanunsignedlongint

voidVb::set_value(constunsignedlonginti);

Vb对象设置一Gauge32对象作为value,该valueSMI32bit的映射。

//setthevaluewitha32bitgauge

voidVb::set_value(constGauge32gauge);

Vb对象设置一TimeTicks对象作为value,该valueSMItimeticks的映射。

//setthevaluewithaTimeTicks

voidVb::set_value(constTimeTickstimeticks);

Vb对象设置一Counter32对象作为value,该valueSMI32bitcounter的映射。

//setvaluewitha32bitcounter

voidVb::set_value(constCounter32counter);

Vb对象设置一Counter64对象作为value,该value用以构成SMI64bitcounter32bit的高位部分与低位部分。

//setvaluetoa64bitcounter

voidVb::set_value(constCounter64c64);

一个Oid设置Vb对象的value部分。

//setvalueforsettinganOid

//createsownspaceforanOidwhich

//needstobefreedwhendestroyed

voidVb::set_value(constOid&varoid);

一个char型的字符串设置一个Vb对象的value部分。事实上,这在内部是用8位字符串作为SMIvalue部分,但是当它是一个ASCII字符串(比如系统标识符)时,这种表示却会显得更简单。

//setvalueonastring

//makesthestringanoctet

//thismustbeanullterminatesstring

voidVb::set_value(constchar*ptr);

一个IPaddress对象设置Vbvalue部分。该成员函数使用了AddressclassIPaddressSMIvalue类型的一种。

//setanIPAddressobjectasavalue

voidVb::set_value(constIpAddressipaddr);

一个IPXaddress对象设置Vbvalue部分。该成员函数使用了AddressclassIPXaddress8SMIvalue类型的一种。

//setanIPXaddressobjectasavalue

voidVb::set_value(constIpxAddressipxaddr);

一个MACaddress对象设置Vbvalue部分。该成员函数使用了AddressclassMACaddress8SMIvalue类型的一种。

//setanMACaddressobjectasavalue

voidVb::set_value(constMacAddressmacaddr);

14.2.4.用一个GenAdress对象设置value

//setanGenAddressobjectasavalue

voidVb::set_value(constGenAddressgenaddr);

14.2.5.用一个Udpadress对象设置value

//setanUdpAddressobjectasavalue

voidVb::set_value(constUdpAddressudpaddr);

14.2.6.用一个IpxSockAdress对象设置value

//setanIpxSockAddressobjectasavalue

voidVb::set_value(constIpxSockAddressipxsockaddr);

14.2.7.用一个Octet对象设置value部分

//setthevalueportiontoaSNMP++Octetobject

voidVb::set_value(constOctetStroctet);

14.2.8.VbClass成员函数GetValue

所有的成员函数Vb::get_value都会修改传进来的参数。如果一个Vb对象不包含被请求的参数类型,该参数不会被修改,并且将返回SNMP_CLASS_INVALID。否则,如果成功将会返回SNMP_CLASS_SUCCESS的状态。

Vb对象获得一个整形value

//getvalueint

//returns0onsuccessandvalue

intVb::get_value(int&i);

Vb对象获得一个长整形value

//getthesignedlongint

intVb::get_value(longint&i);

Vb对象获得一个无符号长整形value

//gettheunsignedlongint

intVb::get_value(unsignedlongint&i);

//getaGauge32

intVb::get_value(Gauge32&gauge);

Vb对象获得一个Gauge32

Vb对象获得一个TimeTicks

//getaTimeTicksfromaVb

intVb:get_value(TimeTicks&timeticks);

Vb对象获得一个Counter32

//getacounterfromaVb

intVb::get_value(Counter32&counter);

Vb对象获得一个64bitcounter

//geta64bitcounter

intVb::get_value(Counter64&counter64);

Vb对象获得一个Oid对象

//gettheOidvalue

//freetheexistingOidvalue

//copyinthenewOidvalue

intVb::get_value(Oid&varoid);

Vb对象获得一个无符号char型字符串(Octetstring

//getaunsignedcharstringvalue

//destructive,copiesintogivenptrofup

//tolenlength

intVb::get_value(unsignedchar*ptr,unsignedlong&len);

Vb对象获得一个char型字符串。该操作获得octetstring部分,并在其后加一空值。

//getachar*fromanoctetstring

//theusermustprovidespaceor

//memorywillbesteppedon

intVb::get_value(char*ptr);

Vb对象获得一个IPaddress对象。IPaddress是一种Address对象。

//getanIPAddress

intVb::get_value(IpAddress&ipaddr);

Vb对象获得一个IPXAddress对象。IpxAddress是一种Address对象。

//getanIPXAddress

intVb::get_value(IpxAddress&ipxaddr);

Vb对象获得一个MACAddress对象。MacAddress是一种Address对象。

//getanMACaddress

intVb::get_value(MacAddress&MACaddr);

Vb对象获得一个GenAddress对象。GenAddress是一种Address对象。

//getangenaddress

intVb::get_value(GenAddress&genaddr);

Vb对象获得一个UdpAddress对象。UdpAddress是一种Address对象

//getanUdpaddress

intVb::get_value(UdpAddress&Udpaddr);

Vb对象获得一个IpxSockAddress对象。IpxSockAddress是一种Address对象

//getanIpxSockAddress

intVb::get_value(IpxSockAddress&IpxSockAddr);

Vb对象获得一个Octet对象

//getanOctetobjectfromaVb

intVb::get_value(OctetStr,&octet);

14.2.9.Vb对象的成员函数GetSyntax

函数并未遵循面向对象规则。如果要知道对象代表的事物,可以通过该函数返回对象内部的id,但同时也破坏了内部数据的隐藏。如果不考虑数据隐藏的话,有些时候可能还是需要知道Vb内部的value,以便抽取出那些隐藏的value。比如,当实现一个浏览器时需要获取Vb,询问Vb有什么数据并取出Vb包含的数据。该操作所返回的Syntaxvalues就是SMISyntaxvalue

//returnthecurrentSyntax

//ThismethodviolatestheOOparadigmbutmaybeusefulif

//thecallerhasaVbobjectanddoesnotkNowwhatitis.

//Thiswouldbeusefulintheimplementationofabrowser.

SmiuiNT32get_Syntax();

14.2.10.检查Vb对象的有效性

通过调用成员函数Vb::valid()可以检查一个Vb对象的实例的有效性。有效的Vb是那些已经获得了Oid的。

//determineifaVbobjectisvalid

intVb::valid();

14.2.11.Vb对象付给另一个Vb对象

通过重载赋值操作符Vb对象可以相互赋值。这种简单的相互赋值避免以下操作:查询一个Vb对象的内容,然后手工将其赋给另一个目标Vb对象。

//overloadedVbassignment

//assignmenttoanotherVbobjectoverloaded

Vb&operator=(const&Vbvb);

14.2.12.Vb对象的错误信息

当用Vb::get_value()一个Vb对象获取数据时,由于Vb数据类型与你所请求的数据类型的不一致将导致一个错误的出现。例如,假设一个Vb对象有一个OctetStr对象,你却要求提取TimeTicks对象。由于无法返回TimeTicksVb::get_value()会失败。当错误事件发生时,相应的调用模块使用Vb::get_Syntax()来询问Vb的实际值或者错误值。

Vb::get_value()returnvalue

说明

SNMP_CLASS_SUCCESS

成功,返回所请求的值

SNMP_CLASS_INVALID

失败,Vbvalue没有包含请求的值

14.3.VbClass例子

下面的例子展示了使用Vbclass的不同方法。除了OidclassVbclass不需要依赖于其他库或模块。以下C++代码ANSI兼容的。

#include“oid.h”

#include“vb.h”

vb_test()

{

//-------[WaystoconstructVbobjects]-------

//constructasingleVbobject

Vbvb1;

//constructaVbobjectwithanOidobject

//thissetstheOidportionoftheVb

Oidd1(“1.3.6.1.4.12”);

Vbvb2(d1);

//constructaVbobjectwithadottedstring

Vbvb3((Oid)“1.2.3.4.5.6”);

//constructanarrayoftenVbs

Vbvbs[10];

//------[WaystosetandgettheOidportionofVbobjects]

//setandgettheOidportion

Oidd2((Oid)“1.2.3.4.5.6”);

vb1.set_oid(d2);

Oidd3;

vb1.get_oid(d3);

if(d2==d3)cout<<“Theybetterbeequal!!\n”;

Vbten_vbs[10];

intz;

for(z=0;z<10;z++)

ten_vbs[0].set_oid((Oid)“1.2.3.4.5”);

//-------[waystosetandgetvalues]

//set&getints

intx,y;

x=5;

vb1.set_value(x);

vb1.get_value(y);

if(x==y)cout<<“xequalsy\n”;

//setandgetlongints

longinta,b;

a=100;

//-------[waystosetandgetvalues]

if(a==b)cout<<“aequalsb\n”;

//set&getunsignedlongints

unsignedlongintc,d;

c=1000;

vbs[0].set_value(c);vbs[0].get_value(d);

if(c==d)cout<<“cequalsd\n”;

//seta64bitcounter

Counter64c64(1000,1001);

vbs[1].set_value(c64);

//getandsetanoidasavalue

Oido1,o2;

o1=“1.2.3.4.5.6”;

vbs[2].set_value(o1);vbs[2].get_value(o2);

if(o1==o2)cout<<“o1equalso2\n”;

//setandgetanoctetstring

unsignedchardata[4],outdata[4];

unsignedlonglen,outlen;

len=4;data[0]=10;data[1]=12;data[2]=12;data[3]=13;

OctetStroctetstr(data,len);

vbs[3].set_value(octetstr);

vbs[3].get_value(octetstr);

//get&setastring

charbeer[80];chargood_beer[80];

strcpy(beer,”SierraNevadaPaleAle”);

vbs[4].set_value(beer);

vbs[4].get_value(good_beer);

printf(“GoodBeer=%s\n”,good_beer);

//getandsetanipanaddress

IpAddressipaddress1,ipaddress2;

ipaddress1=“10.4.8.5”;

vbs[5].set_value(ipaddress1);

vbs[5].get_value(ipaddress2);

cout<<ipaddress2;

}//endvbexample


15.PduClass

SNMP++PduClass的对象模型(ObjectModelingTechnique)视图

SNMP++PduclassSMIProtocolDataUnit(PDU)C++封装。PDU是管理端和代理端进行SNMP通讯的基本概念。通过PduclassSNMP++使得对PDU的操作变得简单、安全。Pduclass允许简单的构造、析构,以及在Pdu对象上加载、卸载Vb对象。因为SNMP++是双效的API,所以Pduclass也是抽象化的,并没有包含SNMPv1或者SNMPv2的特征性的信息。所有发出请求的Snmpclass成员函数都可以只使用一个Pdu对象。Pduclass作为Snmpclass的接口,处理SNMP请求,同时还可作为异步请求和接收notification的回调函数的参数。注意,关于对Vb的存储,Pdu对象是从0开始的(Pdu中第一个vbVb#0)。

大多数地方,SNMP++中的所有Pdu对象都是一样的。即,所有的Pdu对象都有同一性(identity)。唯一的例外是当Pdu对象被用作发送otifications,trapsinforms的时候。为了支持notifications,有3个附加的PduClass成员函数来用作:设置同一性(identity)、时间信息,及Pdu对象的enterprise

15.1.PduClass成员函数列表

PduClassMemberFunctions

说明

Constructors

Pdu::Pdu(void);

构造一个空的Pdu

Pdu::Pdu(Vb*pvbs,constintpvb_count);

一个数组类型的Vb及其长度构造一个Pdu

Pdu::Pdu(constPdu&pdu);

一个Pdu构造另一个

MemberFunctions

intget_vblist(Vb*pvbs,constintpvb_count);

Vb拷贝到调用的参数列表中(vblist

intset_vblist(Vb*pvbs,constintpvb_count);

设置Pdu调用的参数列表中的Vb

intget_vb(Vb&vb,constintindex);

获取Pdu一个指定的Vb

intset_vb(Vb&vb,constintindex);

Pdu设置一个指定的Vb

intget_vb_count();

获取PduVb的个数

intget_error_status();

获取Pdu错误状态

intget_error_index();

获取Pdu错误索引

unsignedlongget_request_id();

获取Pdu的请求标示

unsignedshortget_type();

获取Pdu的类型

intvalid();

判断Pdu的有效性

Intdelete_vb(constintposition);

删除Pdu指定位置上的Vb

inttrim(constinti=1);

删除Pud最后位置上的Vb删除1

MemberFunctionsForInformandTrapUsage

voidset_notify_timestamp(constTimeTicks×tamp);

trapinformPdu设置时间信息

voidget_notify_timestamp(TimeTicks&timestamp);

trapinformPdu获取时间信息

voidset_notify_id(constOidid);

设置trapinformPduID

voidget_notify_id(Oid&id);

获取trapinformPduID

voidset_notify_enterprise(constOid&enterprise);

设置trapinformPduenterpriseID

voidget_notify_enterprise(Oid&enterprise);

获取trapinformPduenterpriseID

OverloadedOperators重载操作符

Pdu&operator=(constPdu&pdu);

一个Pdu付给另一个

Pdu&operator+=(Vb&vb);

一个Pdu增加一个Vb

15.2.PduClass的构造和析构

有多种方法构造Pdu对象,可以有也可以没有构造参数

//constructor,noargs

Pdu::Pdu(void);

//constructorwithVbsandcount

Pdu::Pdu(Vb*vbs,constintvb_count);

//constructorwithanotherPduinstance

Pdu::Pdu(constPdu&pdu);

//destructor

Pdu::~Pdu();

15.3.访问Pdu的成员函数

Pduclass通过多种成员函数支持获取和设置Pdu成员变量。包括获取和设置绑定变量错误信息、请求信息,和类型信息。

//extractalltheVbsfromaPdu

intPdu::get_vblist(Vb*vbs,constintvb_count);

//depositVbstoaPdu

intPdu::set_vblist(Vb*vbs,constintvb_count);

//getaparticularvb

//whereindex0isthe1stvb

intPdu::get_vb(Vb&vb,constintindex);

//setaparticularVb

//whereindex0isthe1stVb

intPdu::set_vb(Vb&vb,constintindex);

//returnthenumberofVbs

intPdu::get_vb_count();

//returntheerrorindex

intPdu::get_error_index();

//gettheerrorstatus

intPdu::get_error_status();

//returntherequestid

unsignedlongPdu::get_request_id();

//getthePdutype

unsignedshortPdu::get_type();

//returnthevalidityofaPdu

intPdu::valid();

15.4.PduClass重载操作符

Pduclass可通过重载操作符,赋值或串连Vb对象到Pdu

//assignmentoperatorforassigningonePdutoanother

Pdu&operator=(constPdu&pdu);

//appendaVbobjecttothePdu’svarbindlist

Pdy&operator+=(Vbvb);

15.5.PduClass处理TrapsInforms的成员函数

当处理notifications,trapsinforms的时候,SNMP++提供了成员函数获取和设置指定的notificationvalue。当使用这些成员函数时,请查阅发送trapsinforms的部分。

//setnotifytimestamp

voidPdu::set_notify_timestamp(constTimeTicks&timestamp);

//getnotifytimestamp

voidPdu::get_notify_timestamp(TimeTicks&timestamp);

//setthenotifyid

voidPdu::set_notify_id(constOidid);

//getthenotifyid

voidPdu::get_notify_id(Oid&id);

//setthenotifyenterprise

voidPdu::set_notify_enterprise(constOid&enterprise);

//getthenotifyenterprise

voidPdu::get_notify_enterprise(Oid&enterprise);

15.6.加载Pdu对象

为了在管理应用中使用Pdu对象,必须在Pdu实例中加载绑定变量表vblist)。这可以通过从多种方法中选择你需要的来处理。一般在发送SNMP请求前加载Pdu

//setnotifytimestamp

voidPdu::set_notify_timestamp(constTimeTicks&timestamp);

//getnotifytimestamp

voidPdu::get_notify_timestamp(TimeTicks&timestamp);

//setthenotifyid

voidPdu::set_notify_id(constOidid);

//getthenotifyid

voidPdu::get_notify_id(Oid&id);

//setthenotifyenterprise

voidPdu::set_notify_enterprise(constOid&enterprise);

//getthenotifyenterprise

voidPdu::get_notify_enterprise(Oid&enterprise);

15.7.加载Pdu对象

为了在管理应用中使用Pdu对象,必须在Pdu实例中加载绑定变量表vblist)。这可以通过从多种方法中选择你需要的来处理。一般在发送SNMP请求前加载Pdu

//exampleofhowtoloadaPduobject

voidload_pdu_examples()

{

Pdupdu;//createaPduobject

Vbvb;//createaVbobject

vb.set_oid(SYSDECR);//settheoidportionoftheVbtoSystemDescriptor

pdu+=vb;//loadstheVbtothePdu

Pdumy_pdu;//createanotherPduobject

Vbvbs[5];//create5vbs

pdu.set_vblist(vbs,5);//loadall5tothepdu

}

15.8.卸载Pdu对象

从阻塞或异步请求中得到请求的Pdu后,都需要将Vb卸载下来才能把SMIvalues取出。

//exampleofhowtounloadaPdu

voidunload_pdu_example(Pdu&pdu)

{

insstaus;

Pdupdu;//createaPduobject

Vbvb;//createaVbobject

vb.set_oid(SYSDECR);//settheoidportionoftheVbtoSystemDescriptor

pdu+=vb;//loadstheVbtothePdu

charmessage[100];//forthesystemdescriptorprintableoctet

Snmpsnmp(status);

if(status!=SNMP_CLASS_SUCCESS){

cout<“SNMP++error=“<<snmp.error_msg(status);

return;

}

pdu.get_vb(vb,0);//unloadthevb

vb.get_value(message);//pullthemessageoutofthevb

cout<<message;//printitout

};


16.SnmpMessageClass

SnmpMessageClass允许对SNMP++对象使用抽象编码规则(ASN.1)和基础编码规则(BER)来编码和解码,进而生成可以在线路上传送的SNMP消息。该class可以方便的串行化Pdu对象,以便于后期的各种使用。大多数SNMP++用户不需要使用这个类,因为Snmpclass已经完成了这项任务,包括管理超时和重发。但是如果程序员想对消息编码,这里也为其提供一种选择,例如很多代理系统就在使用它们自己的传输层。SnmpMessageclass提供的各种成员函数如下表所示:

SnmpMessageClassMemberFunctions

说明

Constructors

SnmpMessage::SnmpMessage(void);

构造一个空的SnmpMessage对象

MemberFunctions

intload(Pdupdu,OctetStrcommunity,

snmp_versionversion);

Pdu、团体名、版本加载一个SnmpMessage对象。版本可以是SNMPv12。返回错误状态。

intload(unsignedchar*data,unsignedlongen);

用原始数据流加载一个SnmpMessage对象。当从线路上收取数据报并通过把它加载到一个SnmpMessage对象来实现解码时,该函数很有用。

intunload(Pdu&pdu,OctetStr&community,

snmp_version&version);

卸载一个已经加载过的SnmpMessage对象。由此可以获得Pdu、团体名、版本

unsignedchar*data();

通过原始的ASN.1/BER串行化数据缓冲区。该缓冲区的范围可以通过成员函数::len()获得

unsignedlonglen()

返回原始数据缓冲区的范围

intvalid();

判断一个SnmpMessage对象的有效性


17.TargetClass

Targetclass一个C++类,在SNMP++中用它来定义和使用target一个targetSNMP通讯中,可以想象成一个代理端的管理层的概念,它由多个网络地址组成。Targets包含了重发和超时机制的信息,还有SNMP协议类型(SNMPv1SNMPv2)等等。目前已有的Targets唯一的子类是Community-basedCTargetCTargetclass可用在SNMPv1SNMPv2的通讯上,由此可以重用你已有的代码SNMPv2通讯中,不需要做修改。通过它,还可以使得一个SNMP++会话与某个特定的代理端的属性无关。

17.1.抽象的Target

SNMP++支持抽象Target的概念。由该抽象Target可以操作所有实际的Target派生类。所有使用TargetSNMP++成员函数接收的都是抽象Target,而不是特指的派生Target对象。当需要支持新的Target时,这种抽象的接口可以减小代码的改动。

17.2.Target地址

每个target都与一个地址对象(Addressobject)相关联。该地址是一个GenAddress,因此可以处理所有SNMP++地址(IP,IPX或其他)。为指明被管理的代理端地址并与一个Target相关联,只需要简单地通过构造函数的参数或成员函数就可实现。

17.3.重发机制

每个Target都具有重发机制,在该机制中定义了超时和重发。由该重发机制可指定等待一个SNMP应答的周期,以及当没有收到一个SNMP应答时进行多少次重发。超时的最小单位被定义成百分之一秒,即当取值为100代表每个应答等待1秒。重发时记录了重发的次数,注意,第一次请求不属于重发,只是发送。所以重发值取3,表示当等待一个应答时最多可以重发3次。等待的总时间可以用下列式子计算:TotalWaitTime=time-out*(retry+1)

如果一个SNMP++应答没有在上式所计算出来的等待总时间内到来,将会返回一个SNMP++超时的错误号。该操作在阻塞和异步两种调用中都可使用。

17.4.TargetClass接口

TargetClassMemberFunctions

说明

Constructors

CTarget::CTarget(void);

构造一个无效的CTarget。重发机制的认值:communitynames“public”retry=1time_out=1

CTarget::CTarget(constAddress&address,

constchar*read_community_name,

constchar*write_community_name,

communitynamesAddressobject构造一个CTarget。重发机制的认值:retry=1time-out=100ms

CTarget(constAddress&address

constOctetStr&read_community_name,

constOctetStr&write_community_name);

OctetStrCommunitiesAddress构造一个CTarget

CTarget::CTarget(Address&address);

Addressobject构造一个CTarget。重发机制的认值:communitynames“public”retry=1time_out=1

CTarget::CTarget(constCTarget&target);

拷贝构造函数

Destructor

CTarget::~CTarget();

删除CTarget对象,释放所有资源。

MemberFunctions

char*get_readcommunity();

返回读权限的community名称

voidget_readcommunity(OctetStr&read_community_oct);

获取OctetStr格式的读权限community

voidset_readcommunity(constchar*get_community);

设置读权限community

voidset_readcommunity(constOctetStr&read_community);

一个OctetStr设置读权限community

char*get_writecommunity();

获取写权限community

voidget_writecommunity(OctetStr&write_community_oct);

获取OctetStr格式的写权限community

voidset_writecommunity(constchar*new_set_community);

设置写权限community

voidset_writecommunity(constOctetStr&write_community);

一个OctetStr设置写权限community

intget_address(GenAddress&address);

获取Addressobject.

voidset_address(Address&address);

设置Address部分

CTarget&operator=(constCTarget&target);

一个CTarget赋给另一个

snmp_versionget_version();

返回SNMP版本(version1version2

voidset_version(constsnmp_versionv);

设置版本(version1version2

intoperator==(constCTarget&lhs,constCTarget&rhs);

比较两个CTargets

AbstractClassMemberFunctions

intvalid();

返回一个Target的有效性

voidset_retry(constintr);

设置重发值

intget_retry();

获取重发值

voidset_timeout(constunsignedlongt);

设置超时值

unsignedlongget_timeout();

获取超时值

17.5.CTargetClass(以Community为基础的Target)

CTargetclass允许显示地定义以Community为基础的Target一个CTarget用以SNMPCommunity为基础的Target定义了一个SNMP代理端。这包含了读权限、写权限communitynamesandanaddress。地址是用SNMP++Addressclass来表示的,所以该地址可以是IP或者IPXaddressAddressclass是个抽象基类,所以可以实现多态操作)。CTargetclass使用前提应该是:应用开发者明确地知道代理端所支持的以SNMPcommunity为基础的访问方式,即SNMPv1SNMPv2

17.5.1.CTarget对象可通过3种不同的方式构建

//----------[instantiatingCTargetobjects]-----------------------------

//validcompleteinstantiation

CTargetct((IpAddress)”10.10.10.10”,//Address

“public”,//readcommunityname

“public”);//writecommunityname

//validcompleteusing“public”defaults

CTargetct((IpAddress)“1.2.3.4”);

//invalidCTarget

CTargetct;

17.5.2.修改CTargets

//----[modifyingCTargets]------------------------------------

ct.set_readcommunity(“private);//modifyingthereadcommunity

ct.set_writecommunity(“private”);//modifyingthewritecommunity

ct.set_address((IpAddress)“15.29.33.210”);

17.5.3.访问CTargets

//-----[AccessingCTargetmembervariables]-------------------------

//getthewritecommunityname

cout<<“Writecommunity”<<ct.get_writecommunity();

//getthereadcommunityname

cout<<“Readcommunity”<<ct.get_readcommunity();

//gettheaddress

GenAddressaddress;

ct.get_address(address);

//checkthevalidityofatarget

if(ct.valid())

cout<<“Targetisvalid”;

17.5.4.CTargets例子

//------------[CTargetclassexamples]-----------------------------------------------------------------

//createavalidCTargetusingaGenAddress

CTargetct((GenAddress)“10.20.30.40”);

//createavalidCTargetusinganIpxAddress

IpxAddressipxaddress(“01010101-010101010101”);

CTargetmy_target(ipxaddress);//usedefault“public”forcommunities

//createaninvalidCTargetobject

CTargetct;//noconstructionparamsthereforinvalid

if(!ct.valid())

cout<<“InvalidCTargetinstance!”;

//getthereadcommunity

cout<<“ReadCommunity=”<<ct.get_readcommunity();

//getthewritecommunity

cout<<“WriteCommunity=”<<ct.get_writecommunity();

//modifythegetcommunity

ct.set_readcommunity(“pilsner”);

//modifythewritecommunity

ct.set_writecommunity(“paleale”);


18.SnmpClass

SNMP++SnmpClass的对象模型(ObjectModelingTechnique)视图

SnmpclassSNMP++中最为重要的类。Snmpclass封装了SNMP的会话。通过处理与指定代理端的会话,SNMP++实现了对网络管理应用的逻辑绑定。会话所控制的是PDU的构建、分发、接受。其他大多数API需要程序员直接操作会话,也即需要提供可靠的传输机制来控制超时、重发、查重。Snmpclass管理了大部分的会话,得到解放的程序员只需要关注于代理端的管理,方便了代码的开发和测试。如果不这样(没有SNMP++),你就只有去设计、实现、测试你自己的SNMP引擎。那么Snmpclass是如何管理通信的呢:1、在UDPIPX连接基础上管理传输层;2、负责打包和解包PDU中的绑定变量;3、分发和接收PDU4、管理所有SNMP所需的资源。

Snmpclass使用简单。它为网络管理应用提供了6种基本操作:Snmp::get,Snmp::set,Snmp::get_next,Snmp::get_bulk,Snmp::inform()Snmp::trap(),每种操作都可分为阻塞和非阻塞(异步)两种方式。当有多个异步的操作同时申请通信时,需要采用多重通信。发送Notification的处理是通过Snmp::trap()Snmp::inform(),即陷阱通知的发送;接收标志信息的处理是通过Snmp::notify_register()Snmp::notify_unregister(),即陷阱通知的接收。

Snmpclass使用安全。构造函数和析构函数完成了对所有资源的加载和卸载,从而减小了内存的崩溃和泄漏的可能性。所有SNMP的内部机制都隐藏起来了,也就避免了不小心而修改到这些内部机制。

Snmpclass可移植。对操作系统和网络系统而言,Snmpclass的接口是可移植的。绝大多数SNMP++的类都可以在任何ANSI/ISOC++编译器上编译和使用。只需要修改少量代码,就可以实现对SNMP++的平台切换。

18.1.SnmpClass成员函数列表

SnmpClassMemberFunctions

说明

Constructor

Snmp::Snmp(int&status);

构造一个Snmp对象,status定义的是成功状态

Destructor

Snmp::~Snmp();

销毁,释放所有资源,关闭会话

MemberFunctions

char*error_msg(constintstatus);

返回所给错误状态的文本字符串

intget(Pdu&pdu,SnmpTarget&target);

调用阻塞方式的SNMPget。从target获取Pdu

intset(Pdu&pdu,SnmpTarget&target);

调用阻塞方式的SNMPset。对target设置Pdu

intget_next(Pdu&pdu,SnmpTarget&target);

调用阻塞方式的SNMPgetnext。针对target上的Pdu

intget_bulk(Pdu&pdu,SnmpTarget&target,

constintnon_repeaters,

constintmax_reps);

调用阻塞方式的SNMPgetbulk(但是V2targets只使用get-next

intinform(Pdu&pdu,SnmpTarget&target);

调用阻塞方式的inform

intget(Pdu&pdu,

snmp_callbackcallback,

void*callback_data=0);

调用SNMP异步get。从target获取Pdu,需要用到用户定义的回调和回调的参数

intset(Pdu&pdu,

void*callback_data=0);

调用SNMP异步set。对target设置Pdu,需要用到用户定义的回调和回调的参数

intget_next(Pdu&pdu,

void*callback_data=0);

调用SNMP异步getnext。从target获取一个Pdu,需要用到用户定义的回调和回调的参数

intget_bulk(Pdu&pdu,

constintmax_reps

snmp_callbackcallback,

void*callback_data=0);

调用SNMP异步getbulk。从target获取批量Pdu,需要用到用户定义的回调和回调的参数

intinform(Pdu&pdu,

void*callback_data=0);

调用异步inform。需要用到notify的回调。

inttrap(Pdu&pdu,SnmpTarget&target);

向指定的target发送一个trap

intnotify_register(TargetCollection&targets,

OidCollection&trapids,

void*callback_data=0);

对接收trapinform的操作注册

intnotify_register(TargetCollection&targets,

AddressCollection&listen_addresses,

void*callback_data=0);

对接收trapinform的操作注册,并用AddressCollection指出监听的接口。

intnotify_unregister();

撤消对接收trapinform的操作注册

intcancel(constunsignedlongrid);

取消针对所给请求id的异步请求的等待

18.2.双效的API

所有的Snmpclass成员函数都是双效的。这就是说对于SNMPversion1version2c,他们可以使用统一的参数表。这解放了程序员,因为程序员不用为了与SNMPversion2的代理端通讯而去修改代码

18.3.SnmpClass的公共成员函数

通过SnmpClass提供的许多成员函数可以创建、管理、终结一个会话。多个Snmp对象可以在同一时间建立。

18.3.1.SnmpClass的构造和析构函数

SnmpClass的构造和析构函数允许开启和关闭会话。通过构建一个Snmp对象来开启一个Snmp会话。由此可对UDPIPX套接口实现构建和管理,直到对象被销毁。Snmp对象可选择被动态或静态的实例化。

18.3.2.SnmpClass构造函数

该构造函数以参数方式返回状态(status)。因为C++的构造函数没有返回值,调用者必须提供一个状态值(status)以供实例化对象后针对状态的检查。调用者需要检查返回值是否是“SNMP_CLASS_SUCCESS”。如果构造函数的状态不表示成功,该会话也就不可用。

//constructor,blockedSNMPobject

Snmp::Snmp(int&status);//constructionstatus

18.3.3.SnmpClass析构函数

SnmpClass的析构函数关闭相应的会话,并释放所有资源和内存

//destructor

Snmp::~Snmp();

18.3.4.SnmpClass发送请求的成员函数

为了访问或修改代理端的MIB,请求必须通过Snmp::get(),Snmp::set(),Snmp::get_next(),Snmp::get_bulk(),Smnp::inform()以及Snmp::trap()来发送。所有这些成员函数接受同样的参数表。

18.3.5.SnmpClass的阻塞方式成员函数Get

阻塞方式的成员函数get允许从指定target的代理端获取对象。调用者必须指定目标target以及要请求的Pdu

//--------[get]-------------------------------------------

intSnmp::get(Pdu&pdu,//Pdutoget

SnmpTarget&target);//specifiedtarget

18.3.6.SnmpClass的阻塞方式成员函数GetNext

阻塞方式的成员函数getnext可以用来遍历代理端的MIB

//---------[getnext]--------------------------------------

intSnmp::get_next(Pdu&pdu,//Pdutogetnext

SnmpTarget&target);//specifiedtarget

18.3.7.SnmpClass的阻塞方式成员函数Set

阻塞方式的成员函数set允许设置代理端的对象

//---------[set]--------------------------------------------

intSnmp::set(Pdu&pdu,//Pdutoset

SnmpTarget&target);//specifiedtarget

18.3.8.SnmpClass的阻塞方式成员函数GetBulk

SNMP++SNMPversion1version2Target提供了一个获取批量数据的接口。在SNMPversion1中的相应操作对应到成员函数getnext

//--------[getbulk]-------------------------------------------

intSnmp::get_bulk(Pdu&pdu,//pdutoget_bulk

Target&target,//destinationtarget

constintnon_repeaters,//nonrepeaters

constintmax_reps);//maximumreps

18.3.9.SnmpClass的阻塞方式成员函数Inform

SNMP++提供了一个Inform接口,由此可直接在V2的代理端和网管端内部之间发送消息。

//-----------[inform]----------------------------------------------------------

intSnmp::inform(Pdu&pdu,//pdutosend

SnmpTarget&target);//destinationtarget

一个Inform指定其Id

InformID的指定方法trapID一样。可通过用成员函数Pdu::set_notify_id()来为一个informPDU指定其IDInform标识符ID代表了其使用的Oid。为了建立InformID,可以用需要的InformID值来直接建立一个Oid对象,然后用成员函数Pdu::set_notify_id()一个Pdu加载在其上。反过来,一个informID可以用成员函数Pdu::get_notify_id()获取

Inform上指定TimeStamp时间信息

要给一个informPDU指定时间信息,可用成员函数Pdu::set_notify_timestamp()。如果一个Pdu没有用该成员函数就发出去了,那么会使用一个来自SNMP++引擎认的timestamp

18.4.SnmpClass的异步方式成员函数

一个Snmp实例可以支持阻塞与异步两种方式的请求。异步请求将会立即返回所控制的线程,并不需要等待呼叫者的应答。为了达到该目的,使用了所谓的回调程序机制。当发出异步请求时,调用者必须指定回调函数,还可选择性的指定一个回调函数的参数。

18.4.1.SNMP++异步回调函数的类型定义

typedefvoid(*snmp_callback)(int,//reason

SnmP*,//sessionhandle

Pdu&,//Pdupassedin

SnmpTarget&,//sourcetarget

void*);//callbackdata

18.4.1.1.回调的参数说明

Reason(s),int

该整形的原因参数描述了调用回调的原因。回调被调用的原因包括以下几种:

SNMP_CLASS_ASYNC_RESPONSE:收到了一个SNMP应答。这可以是一个来自get,set,get-next,get-bulkinform的应答。用Pdu参数保存实际应答的PDU,用SnmpTarget参数保存发送应答的target

SNMP_CLASS_TIMEOUT:一个SNMP++请求超时,该请求由target实例提供的超时与重发信息的机制来处理。为了重用,用Pdu参数保存Pdu请求的原值,用SnmpTarget参数保存target的原值。

SNMP_CLASS_SESSION_DESTROYED:会话被销毁,此时所有正在等待的异步请求都不会完成。

SNMP_CLASS_NOTIFICATION:收到一个notification,trapinform请求。Pdu对象会保存实际的notify,通过Pdu成员函数Pdu::get_notify_id(),Pdu::get_notify_timestamp()Pdu::get_notifty_enterprise()来获得notificationid,timestampenterprise

Snmp++Session,SnmP*

该参数保存发送请求的会话的值。由此可以在time-outget-next情况下实现会话的重用。

ResponsePDU,Pdu&

该参数为esponse,notifietrap保存了应答Pdu”。当原因reason参数)为失败时,Pdu参数保存了请求Pdu”的原值。一旦Pdu对象越界,其值就不可得了。

Target,SnmpTarget&

该参数为response,notifietrap保存了Pdu的来源。如果原因reason参数)为失败,当有请求发出时,target的原值就会被用到。

Callbackdata,void*

当有请求发出时,回调的参数可以作为一个可选的参数提供。如果指定了该参数,将会返回相关信息。如果没有指定,该值取空(null)。

18.4.2.取消一个异步请求

SNMP++允许在完成之前取消相应的异步请求。这很有用,尤其当你需要在代码中提前退出或指定的回调已经失效的时候。当Snmp对象发出的请求被销毁时,异步请求会自动取消,这时指定的回调会收到一个“SNMP_CLASS_SESSION_DESTROYED”的原因。另一方面,可以用成员函数Snmp::cancel()来取消单个的异步请求。该成员函数通过参数request_id无影响的取消对应的异步请求。

//-------------[cancelarequest]-----------------------------------

intSnmp::cancel(constunsignedlongrid);

18.4.3.SnmpClass的异步成员函数Get

异步get允许从指定的代理端获取SNMP对象。当请求PDU”发出后,异步get调用就会返回,它不会等待应答PDU”。当收到应答PDU”时,会调用程序员定义的回调。在回调中,可以用任何喜欢的方式实现有效的应答。

//------------------------[getasync]----------------------------------

intSnmp::get(Pdu&pdu,//Pdutogetasync

SnmpTarget&target,//destinationtarget

snmp_callbackcallback,//asynccallback

void*callback_data=0);//callbackdata

18.4.4.SnmpClass的异步成员函数Set

异步成员函数set的工作方式与get雷同。

//------------------------[setasync]----------------------------------

intSnmp::set(Pdu&pdu,//Pdutosetasync

SnmpTarget&target,//asynccallback

void*callback_data=0);//callbackdata

18.4.5.SnmpClass的异步成员函数GetNext

异步成员函数get-next的工作方式与异步getset雷同。

//------------------------[getnextasync]-----------------------------

intSnmp::get_next(Pdu&pdu,//Pdutoget_next

SnmpTarget&target,//destination

snmp_callbackcallback,//asynccallback

void*callback_data=0);//callbackdata

18.4.6.SnmpClass的异步成员函数GetBulk

异步成员函数get-bulk的工作方式与异步getset雷同。

//------------------------[getbulkasync]-----------------------------

intSnmp::get_bulk(Pdu&pdu,//Pdutoget_bulkasync

Target&target,//nonrepeaters

constintmax_reps,//maxrepetitions

snmp_callbackcallback,//asynccallback

void*callback_data=0);//callbackdata

18.4.7.SnmpClass的异步成员函数Inform

//--------------------[informasync]----------------------------------------

intSnmp::inform(Pdu&pdu,//pdutosend

SnmpTarget&target,//callbackfunction

void*callback_data=0);//callbackdata

18.5.SNMP++通知方法

SNMP++API支持收发trap的成员函数

18.5.1.发送Trap

发送trap函数一个有用的管理程序(managerAPI。可用函数与其他管理端进行通讯。

//-----------------------[sendatrap]----------------------------------

intSnmp::trap(Pdu&pdu,//Pdutosend

SnmpTarget&target);//destinationtarget

18.5.1.1.发送Trap的成员函数的参数说明

Pdu&pdu

要发送的Pdu,它是trap所包含的有效负载

SnmpTarget&target

发送Trap的目的地

指定一个TrapId

TrapId的指定方式与InformId一样。可用成员函数Pdu::set_notify_id()来指定trapPDUIDTrap标识符IDSMISNMPv2中是以Oid表示的。SNMP++预定义了以下6种通用的trapOid。只需用想要的trapid值来赋给一个Oid对象就可以生成一个trapid。相反的,可用成员函数Pdu::get_notify_id()获取trapid

SNMP++为通用TrapID定义的Oid对象

coldStart("1.3.6.1.6.3.1.1.5.1”)

warmStart("1.3.6.1.6.3.1.1.5.2”)

linkDown("1.3.6.1.6.3.1.1.5.3”)

linkUp("1.3.6.1.6.3.1.1.5.4”)

authenticationFailure("1.3.6.1.6.3.1.1.5.5”)

egpNeighborLoss("1.3.6.1.6.3.1.1.5.6”)

如果要发送某个企业指定的trap调用者可能需要指定一个除上面以外的Oid

指定Trap的时间信息

可用成员函数Pdu::set_notify_timestamp()来指定trapPDU的时间信息。如果一个Pdu调用这个成员函数就发送了,那么会使用一个来自SNMP++引擎的时间信息。

18.5.1.2.指定TrapEnterprise

不用被企业指定的trap困扰,任何trap的企业都代表了产生trap的代理端的MIB。对trap的发送者来说它是系统标识符(SystemObjectIdentifier),但是从理论上讲它可以表示任何Oid的值。为了设置该参数,SNMP++允许使用成员函数Pdu::set_notify_enterprise()来设置enterprise,而且这个参数是可选的。如果使用了所提供的enterprise,该enterprise会加载在对应的Pdu对象上。

18.5.1.3.给SNMPv1Trap指定特殊的Trap

为了给SNMPv1Trap指定特殊的Trap值,trapidOid应该构造如下:trapid的最末子idsubid)代表指定的要使用的值;倒数第二个子id应该是零。即,为了指定特殊的Trap值,需要添加两个额外的子id一个是零、一个是值(“0.X”)。这个约定与规定SNMPv1SNMPv2trap映射的RFC1452的描述一致。

18.5.2.接收Notification

接收SNMP++trapinform的时候,允许应用程序使用指定的过滤器来接收trapinform。不像其他的SNMP操作,trapinform是在任何可能出现的时候主动发出的。因此informstraps属于异步的动作。通过SNMP++提供的成员函数调用者可以指定informstraps的过滤器。可用informstraps的类型、来源和目标来过滤informstraps

//-----------------------[registertoreceivetrapsandinforms]-------------------------------------------

//defaultformlistensonalllocalinterfacesusingwellkNownport/socket#’s

intSnmp::notify_register(OidCollection&ids,//typestolistenfor

TargetCollection&targets,//targetstolistenfor

snmp_callbackcallback,//callbacktouse

void*callback_data=0);//optionalcallbackdata

//------------------------[registertoreceivetrapsandinforms]----------------------------------------

//alternateform,AddressCollectionallowslocallisteninterfacespecification

intSnmp::notify_register(OidCollection&ids,//targetstolistenfor

AddressCollection&local_interfaces,//interfacestolistenon

snmp_callbackcallback,//callbacktouse

void*callback_data=0);//optionalcallbackdata

//-----------------------[un-registertogettrapsandinforms]------------------------------------------

intSnmp::notify_unregister();

18.5.2.1.注册TrapInform

每个Snmpclass实例可以为它们自己的traps/informs注册。也就是说,一个Snmp对象可以有它自己的一套过滤器和回调,当收到的trapinform满足过滤条件时就会调用。当每个新的呼叫清理了先前的过滤器设置时,成员函数Snmp::notify_register()可能会多次被调用。当调用成员函数Snmp:notify_unregister()Snmp实例撤消时,相应的接收Trap/inform的会话将会终止。

18.5.2.2.Snmp::notify_register()的基本形式

notification注册基本形式中包括notification类型、notification来源、过滤参数、OidCollectionTargetCollection。使用该形式的notify_register()会在所有本地端口上触发notification的监听。所以如果本地机器有多重初始地址,即它会有多重网络接口,所有的接口将会被开启,并使用已知的port/socket来接收notify。例如:如果我的机器是双网卡的,两个卡都支持IPInternetProtocol)协议,其中一个支持IPXInternetExchangeProtocol)协议;如果调用基本形式的notify_register(),则会在两个IP接口上使用已知的SNMPtrap端口,在IPX接口上使用已知的trapIPX套接字(socketnumber)。

18.5.2.3.Snmp::notify_register()的备用形式

作为备用,重载形式的notify_register()可接受一个附加参数,进而允许指定本地接口来监听informAddressCollectionAddressCollection参数包含了一组需要监听的Address对象列表,包括IpAddresses,IpxAddresses,UdpAddressesIpxSockAddresses。下表描述了AddressCollection以及notify_register()的运作方式:

AddressCollectionElementBehaviorDeFinition

AddressClass

Value

说明

IpAddress

Anyvalueexcept0.0.0.0

用已知的IP端口监听指定的IP接口

IpAddress

0.0.0.0

用已知的IP端口监听所有IP接口

UdpAddress

Anyvalueexcept0.0.0.0

用已知的UDP端口监听指定的UDP接口

UdpAddress

0.0.0.0

用已知的UDP端口监听所有UDP接口

IpxAddress

Anyvalueexcept00000000:000000000000

用已知的IPX端口监听指定的IPX接口

IpxAddress

00000000:000000000000

用已知的IPX端口监听所有IPX接口

IpxSockAddress

Anyvalueexcept00000000:000000000000

用已知的IPX套接字监听指定的IPX接口

IpxSockAddress

00000000:000000000000

用已知的IPX套接字监听所有IPX接口

18.5.2.4.notify_regsiter()的过滤功能

当需要过滤时,过滤器的行为如下:如果收到的informtrapOidCollection中的id单元(item)一致,并且收到的informtrapTargetCollection中的单元一致,则相应的inform/trap会被送到调用者指定的回调中。注意,如果OidCollection为空,则所有的inform都将通过id检查,同样的,如果TargetCollection为空,则所有的inform都将通过Target检查。

18.5.3.使用OidCollection,TargetCollectionAddressCollections过滤

SNMP++提供了3种有序集合的collectionclasse,共同来收集Oids,TargetsAddresses。所有collectionclasse操作形式都一样,因为它们是从同样的C++模板类SnmpCollection派生来的。统一的集合操作如下:

TargetandOidCollectionClassMemberFunctions

说明

Constructors

SnmpCollection::SnmpCollection(void);

构造一个空的集合

SnmpCollection::SnmpCollection(constT&t);

用单一元素构造一个集合

Destructors

SnmpCollection::SnmpCollection();

销毁集合,释放所有资源

MemberFunctions

intsize();

返回集合的大小

SnmpCollection&operator+=(T&t);

增加一个元素到集合

SnmpCollection&operator=(SnmpCollection&collection);

一个集合赋给另一个

T&operator[](intp);

访问集合中的一个元素

intset_element(constT&i,constintp);

在集合种设置一个已有的元素

intget_element(T&i,constintp);

从集合获取一个元素

18.5.3.1.生成并使用集合作为过滤器

生成并使用SnmpCollections作为接收一个trap/inform的过滤器是简单而直接的。Notify注册函数3个参数:TargetCollection,OidCollectionAddressCollection。要构造这些过滤器,首先得实例化一个集合,然后用重载的操作符“+=”把元素加入其中。

//exampleofmakingtrapreceptionfilters

//targetcollection

TargetCollectionmy_targets;

my_targets+=cisco_router;

my_targets+=fore_switch;

//Oidcollection

OidCollectionmy_trapids;

my_trapids+=coldStart;

my_trapids+=warmStart;

//Addresscollection

AddressCollectionmy_addresses;

my_addresses+=(IpAddress)“10.4.8.5”;

my_addresses+=(GenAddress)“01020304:010203040506”;

18.6.SNMP++Class返回的错误

使用SNMP++时,可返回多种错误编号。这些错误号可穿越平台,进而帮助应用的开发者发现并检查错误条件。

18.6.1.SnmpClass的错误消息成员函数

如果在使用Snmp成员函数过程中出现了一个错误,成员函数Snmp::error_msg()可以用来检索出一个友好的错误字符串。

//------------------------[errormessage]-----------------------------

char*Snmp::error_msg(constintstatus);//returnsstringforprovidedstatus


19.运行模式

SNMP++的设计决定了它支持多种运行模式。这些运行模式允许用户创建图形用户接口(GUI)以及控制台模式的应用。GUI运行模式与现有的GUI事件驱动系统协同工作;而控制台运行模式允许使用自定义的事件驱动系统,甚至不需要事件驱动系统。

19.1.Microsoftwindows事件驱动系统的运作

为了在MS-Windows上使用,SNMP++MS-Windows消息系统协同工作。调用阻塞模式可以允许处理其他消息。

19.2.OpenSystemsFoundation(OSF)X11Motif的运作

X11接口与MS-Windows接口一样。在MS-WindowsX11各种版本上的SNMP++支持阻塞和异步方式的使用。为了用SNMP++X11应用注册X11的上下文(context)需要一个额外的函数(该操作是为了在X11的事件系统上使用SNMP++)。这就要用到XtAppMainLoop()或类似的函数来显式地认可并分发所有异步的SNMP++事件。

·需要传入的上下文参数会由XtAppInitialize()调用返回

·如果对X11注册成功,则该函数返回零

//----------------[initializeSNMP++X11Context]--------------------------

intSNMPX11Initialize(XtAppContextcontext);

19.3.不以GUI为基础的应用的运作

SNMP++的第三种运作模式是用文本形式构造的控制台应用。这些类型的应用上的操作也可以调用阻塞或异步的模式。SNMP++提供了一组函数调用来读取当前用到的文件描述符(sockethandles)。调用者在它们各自的“select”调用中用到这些文件描述符。如果SNMP++文件描述符有一个挂起的事件,调用者将激活例行程序来处理所有挂起的事件。

SNMPGetFdSets

用以决定需要潜在地激活的文件描述符。该函数会填充读、写、异常模块,以便传递到“select”

//-------[getfiledescriptorsetfromSNMP++]------------------------------------

voidSNMPGetFdSets(int&maxfds,//max#offdsrepresented

fd_set&read_fds,//maskrepresentingreadactions

fd_set&write_fds,//maskrepresentingwriteactions

fd_set&exceptfds);//maskrepresentingexceptionactions

SNMPGetNextTimeout

用以决定下次出现超时事件的时间。该值可在阻塞操作中被用作最大间隔值。比如select在控制权返回之前必须等待该间隔时间。超时的计算的基础是:所有用户注册超时(user-registeredtime-outs)以及SNMP重发的时间间隔中最近的一次。

//---------[Getthenexttime-outvalue]----------------------------------------------------

unsignedlongintSNMPGetNextTimeout();//returnsvaluein1/100ofseconds

SNMPProcesspendingEvents

用以处理目前所有的突出的(outstanding)事件。该函数调用所有与已完成的超时、文件描述符或突出的(outstandingSNMP消息相关的回调。该函数是非阻塞的,在同一时候它只处理突出的(outstanding)事件。

//------[processpendingevents]----------------------------------------------------------

intSNMPProcesspendingEvents();


20.状态&错误编号

当使用Snmpclass操作的时候SNMP++提供了两种级别的错误信息。所有的Snmpclass成员函数都返回一个状态值。“SNMP_CLASS_ERR_STATUS_SET”这个特别的错误值表明了Pdu发生了一个内部错误,必须用成员函数Pdu::get_error_status()来检索该错误信息。所有的SNMP++错误值都可传进成员函数Snmp::err_msg()以打印出该错误的文本描述。

SNMP++GeneralErrors

Value

说明

SNMP_CLASS_SUCCESS

0

成功状态

SNMP_CLASS_ERROR

-1

普通错误

SNMP_CLASS_RESOURCE_UNAVAIL

-2

内存分配失败(Newmalloc

SNMP_CLASS_INTERNAL_ERROR

-3

未知的内部错误

SNMP_CLASS_UNSUPPORTED

-4

不支持函数

CallbackReasons

SNMP_CLASS_TIMEOUT

-5

明显的请求超时

SNMP_CLASS_ASYNC_RESPONSE

-6

收到应答

SNMP_CLASS_NOTIFICATION

-7

收到notification(trap/inform)

SNMP_CLASS_SESSION_DESTROYED

-8

销毁Snmp对象

SnmpClassErrors

SNMP_CLASS_INVALID

-10

在无效的实例上调用Snmp成员函数

SNMP_CLASS_INVALID_PDU

-11

向映像函数传递了无效的PDU

SNMP_CLASS_INVALID_TARGET

-12

向映像函数传递了无效的target

SNMP_CLASS_INVALID_CALLBACK

-13

向映像函数传递了无效的回调函数

SNMP_CLASS_INVALID_REQID

-14

要取消的请求ID无效

SNMP_CLASS_INVALID_NOTIFYID

-15

trap/informOid丢失

SNMP_CLASS_INVALID_OPERATION

-16

指定的target不允许进行Snmp操作

SNMP_CLASS_INVALID_OID

-17

向映像函数传递了无效的Oid

SNMP_CLASS_INVALID_ADDRESS

-18

向映像函数传递了无效的address

SNMP_CLASS_ERR_STATUS_SET

-19

代理端返回带有错误信息的应答PDU

SNMP_CLASS_TL_UNSUPPORTED

-20

不支持的传输

SNMP_CLASS_TL_IN_USE

-21

传输被占用

SNMP_CLASS_TL_Failed

-22

传输失败


21.错误状态值

SNMP++的成员函数返回值是“SNMP_CLASS_ERR_STATUS_SET”时,可以由成员函数Pdu::get_error_status()获取一个额外的错误状态。该值表示的是RFC1905中实际的SMIPDU错误状态值。这些值可以传进成员函数Snmp::err_msg()以友好的方式描述。

PduErrorStatusMacro

Value

说明

SNMP_ERROR_TOO_BIG

1

Pdu太大,查看错误索引

SNMP_ERROR_NO_SUCH_NAME

2

没有对应的帮定变量名称,查看返回的错误索引

SNMP_ERROR_BAD_VALUE

3

错误的帮定变量,查看返回的错误索引

SNMP_ERROR_READ_ONLY

4

帮定变量是只读的,查看返回的错误索引

SNMP_ERROR_GENERAL_VB_ERR

5

普通帮定变量错误,查看返回的错误索引

SNMP_ERROR_NO_ACCESS

6

操作失败,拒绝访问

SNMP_ERROR_WRONG_TYPE

7

操作失败,类型错误

SNMP_ERROR_WRONG_LENGTH

8

操作失败,长度错误

SNMP_ERROR_WRONG_ENCODING

9

操作失败,译码错误

SNMP_ERROR_WRONG_VALUE

10

操作失败,值错误

SNMP_ERROR_NO_CREATION

11

操作失败,拒绝创建

SNMP_ERROR_INCONSIST_VAL

12

操作失败,值不相容

SNMP_ERROR_RESOURCE_UNAVAIL

13

操作失败,无法使用资源

SNMP_ERROR_COMITFAIL

14

操作失败,提交失败

SNMP_ERROR_UNDO_FAIL

15

操作失败,撤销失败

SNMP_ERROR_AUTH_ERR

16

操作失败,权限错误

SNMP_ERROR_NOT_WRITEABLE

17

操作失败,拒绝更改

SNMP_ERROR_INCONSIS_NAME

18

操作失败,名字不相容


22.SnmpClass例子

关于这个部分的附加例子,请查阅下表所列的文档,以获得可用作命令的完整实用程序。

ProgramNameand说明

FileName

SnmpGet,performsSNMP++gettov1andv2agents.

snmpget.cpp

SnmpNext,peformsSNMP++getNexttov1andv2agents.

snmpnext.cpp

SnmpBulk,performsSNMP++getBulktov1andv2agents.

snmpbulk.cpp

SnmpSet,performsSNMP++settov1andv2agents.

snmpset.cpp

SnmpTrap,sendsv1orv2traptoamanager.

snmptrap.cpp

SnmpWalk,walksanagent'sMIBusingv1orv2viaGetBulk.

snmpwalk.cpp

22.1.GettingaSingleMIBVariableExample

#include“snmp_pp.h”

#definesYSDESCR“1.3.6.1.2.1.1.1.0”//ObjectIDforSystemDescriptor

voidget_system_descriptor()

{

intstatus;//returnstatus

CTargetctarget((IpAddress)“10.4.8.5”);//SNMP++v1target

Vbvb(SYSDESCR);//SNMP++VariableBinding

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;}

//-------[InvokeaSNMP++Get]-------------------------------------------------------

pdu+=vb;//addthevariablebinding

if((status=snmp.get(pdu,0);//extractthevariablebinding

cout<<“SystemDescriptor=”<<vb.get_printable_value();}//printout

};

22.2.GettingMultipleMIBVariablesExample

#include“snmp_pp.h”

#definesYSDESCR“1.3.6.1.2.1.1.1.0”//ObjectIDforsystemdescriptor

#definesYSOBJECTID"1.3.6.1.2.1.1.2.0"//ObjectIDforsystemobjectID

#definesYSUPTIME"1.3.6.1.2.1.1.3.0"//ObjectIDforsystemuptime

#definesYSCONTACT"1.3.6.1.2.1.1.4.0"//ObjectIDforsystemcontact

#definesYSNAME"1.3.6.1.2.1.1.5.0"//ObjectIDforsystemname

#definesYSLOCATION"1.3.6.1.2.1.1.6.0"//ObjectIDforsystemlocation

#definesYSSERVICES"1.3.6.1.2.1.1.7.0"//ObjectIDforsystemservices

voidget_system_group()

{

intstatus;//returnstatus

CTargetctarget((IpAddress)“10.4.8.5”);//SNMP++v1target

Vbvb[7];//avbforeachobjecttoget

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;}

//-------[buildupthevbstoget]-----------------------------------------------------------------

vb[0].set_oid(SYSDESCR);

vb[1].set_oid(SYSOBJECTID);

vb[2].set_oid(SYSUPTIME);

vb[3].set_oid(SYSCONTACT);

vb[4].set_oid(SYSNAME);

vb[5].set_oid(SYSLOCATION);

vb[6].set_oid(SYSSERVICES);

//----[appendallthevbstothepdu]-----------------------------------------------------

for(intz=0;z<7;z++)

pdu+=vb[z];

//-------[InvokeaSNMP++Get]-------------------------------------------------------

if((status=snmp.get(pdu,ctarget))!=SNMP_CLASS_SUCCESS)

cout<<snmp.error_msg(status);

else{

pdu.get_vbs(vb,7);//extractthevariablebindings

for(intw=0;w<7;w++)

cout<<vb[w].get_printable_value()<<“\n”;}//printoutthevalue

};

22.3.SettingaSingleMIBVariableExample

#include“snmp_pp.h”

#definesYSLOCATION“1.3.6.1.2.1.1.6.0”//ObjectIDforSystemlocation

voidset_system_location()

{

intstatus;//returnstatus

CTargetctarget((IpAddress)“10.4.8.5”);//SNMP++v1target

Vbvb(SYSLOCATION);//SNMP++VariableBinding

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;

}

//-------[InvokeaSNMP++Set]-------------------------------------------------------

vb.set_value(“Upstairsmezzanine”);//addlocationstringtovb

pdu+=vb;//addthevariablebinding

status=snmp.set(pdu,ctarget);

cout<<snmp.error_msg(status);

}


22.4.SettingMultipleMIBVariablesExample

#include“snmp_pp.h”

#definesYSCONTACT"1.3.6.1.2.1.1.4.0"//ObjectIDforsystemcontact

#definesYSNAME"1.3.6.1.2.1.1.5.0"//ObjectIDforsystemname

#definesYSLOCATION"1.3.6.1.2.1.1.6.0"//ObjectIDforsystemlocation

voidmulti_set()

{

intstatus;//returnstatus

CTargetctarget((IpAddress)“10.4.8.5”);//SNMP++v1target

Vbvb[3];//avbforeachobjecttoget

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;}

//-------[buildupthevbstoget]-----------------------------------------------------------------

vb[0].set_oid(SYSCONTACT);

vb[0].set_value(“AlanTuring”);

vb[1].set_oid(SYSNAME);

vb[1].set_value(“TheTuringMachine”);

vb[2].set_oid(SYSLOCATION);

vb[2].set_value(“Cambridge,UK”);

//----[appendallthevbstothepdu]-----------------------------------------------------

for(intz=0;z<3;z++)

pdu+=vb[z];

//-------[InvokeaSNMP++Set]-------------------------------------------------------

status=snmp.set(pdu,ctarget);

cout<<snmp.error_msg(status);

}

22.5.WalkingaMIBusingGet-NextExample

#include“snmp_pp.h”//includesnmp++headerfile

voidmib_walk()

{

intstatus;//returnstatus

CTargettarget((IpAddress)“10.4.8.5”);//SNMP++v1target

Vbvb;//aSNMP++vb

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;}

//-------[setupthefirstvb]---------------------------------------------------------------

vb.set_oid(“1”);//getnextstartingseed

pdu+=vb;//addvbtothepdu

status=SNMP_CLASS_SUCCESS;

while(status==SNMP_CLASS_SUCCESS)

{

if((status=snmp.get_next(pdu,ctarget))==SNMP_CLASS_SUCCESS){

pdu.get_vb(vb,0);//extractthevb

cout<<“MibObject=“<<vb.get_printable_oid()<<“\n”;

cout<<“MibValue=“<<vb.get_printable_value()<<“\n”;

pdu.set_vb(vb,0);//uselastvbasthenextone

}

else

cout<<“SNMP++Error=“<<snmp.error_msg(status);

}

};

22.6.SendingaTrapExample

#include“snmp_pp.h”

voidsend_trap()

{

intstatus;//returnstatus

CTargettarget((IpAddress)“10.4.8.5”);//SNMP++v1target

Pdupdu;//SNMP++PDU

//-------[ConstructaSNMP++SNMPObject]---------------------------------------

Snmpsnmp(status);//CreateaSNMP++session

if(status!=SNMP_CLASS_SUCCESS){//checkcreationstatus

cout<<snmp.error_msg(status);//iffail,printerrorstring

return;}

status=snmp.trap(pdu,target,coldStart);

cout<<“TrapSendStatus=“<<snmp.error_msg(status);

};

22.7.ReceivingTrapsExample

#include“snmp_pp.h”

//-----------------[trapcallbackfunctiondeFinition]-------------------------------------------------------------------

voidmy_trap_callback(intreason,//reason

SnmP*session,//sessionhandle

Pdu&pdu,//trappdu

TimeTicks×tamp,//timestamp

SnmpTarget&target,//sourceofthetrap

void*cbd)//optionalcallbackdata

{

Address*address;

unsignedcharget_cummunity[80],set_community[80];

unsignedlongtimeout;

intretry;

if(reason==SNMP_CLASS_TRAP){

target.resolve_to_C(get_community,//getcommunity

set_community,//setcommunity

&address,//addressobject

timeout,//timeout

retry);//retry

cout<<“TrapReceivedfrom<<address->get_printable()<<“TrapId=“<<trapid.get_printable();

}

else

cout<<“TrapReceiveError=“<<session->error_msg(reason);

};

//---------------[trapreceiveregister]---------------------------------------------------------------------

SnmP*snmp;//dynamicSnmpobject

voidtrap_register()

{

//----------------[instantiateanSnmpobject,deletewhennolongerreceivingtraps]------------

intstatus;

snmp=newSnmp(status);

if((snmp==NULL)||(status!=SNMP_CLASS_SUCCESS))

cout<<“ErrorconstructingSnmpObject\n”;

else

{

//-------[setuptwoemptycollections,emptydenotesreceiveall]-------------------------------

TargetCollectiontargets;

OidCollectiontrapids;

//------[invoketheregsiter]----------------------------------------------------------------------------

if(status=snmp->notify_register(trapids,targets,&my_trap_callback))!=SNMP_CLASS_SUCCESS)

cout<<“SnmpTrapRegisterError“<<snmp->error_msg(status);

}

};


23.参考书目

[Banker,Mellquist]

BankerKim,MellquistPeterE.,SNMP++,Connexions,TheInteroperabilityReport,Volume9,No.3,march1995.

[Comer]

Comer,DouglasE.,InternetworkingwithTCP/IP,Principles,ProtocolsandArchitecture,VolumeIPrenticeHall,1991.

[Gama,Helm,Johnson,Vlissides]

ErichGama,RichardHelm,RalphJohnson,JohnVlissides,DesignPatterns,AddisonWesley,1995.

[Meyers]

Meyers,Scott,EffectiveC++,1994.

[Petzold]

PetzoldCharles,ProgrammingMS-Windows,MicrosoftPress

[RFC1452]

J.Case,K.Mccloghrie,M.Rose,S.Waldbusser,Coexistencebetweenversion1andversion2oftheInternet-standardNetworkManagementFramework,May03,1993.

[RFC1442]

J.Case,StructureofManagementinformationforversion2oftheSimpleNetworkManagementProtocol(SNMPv2),1993.

[Rose]

Rose,MarshallT.,TheSimpleBook,AnIntroductiontoInternetManagement,SecondEdition,PrenticeHallSeries1994.

[Rumbaugh]

Rumbaugh,James,Object-OrientedModelingandDesign,PrenticeHall,1991.

[Saks]

Saks,Dan,C++ProgrammingGuidelines,ThomasPlum&DanSacks,1992.

[Stallings]

Stallings,William,SNMP,SNMPv2andCMIPThePracticalGuidetoNetworkManagementStandards,1993.

[Stroustrup]

Stroustrup,Bjarne,TheC++ProgrammingLanguage,Edition#2AddisonWesley,1991.

[WinSNMP]

WinSNMP,WindowsSNMPAnopenInterfaceforProgrammingNetworkManagementApplicationunderMicrosoftwindows.Version1.1.

[WinSockets]

WinSockets,WindowsSockets,AnopenInterfaceforNetworkProgrammingunderMicrosoftwindows.

原文地址:https://www.jb51.cc/vb/260166.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐