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. 完整的一套SNMP C++... 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, Get Next, Get Bulk, Set, InformTrap的操作... 11

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

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

4.1. WinSNMP Version 1.1的使用... 12

4.2. 对IPIPX的支持... 12

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

4.4. 与HP OpenView for Windows 兼容... 12

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

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

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

5.3. 与HP OpenView for UNIX 兼容... 13

6. SNMP Syntax Classes. 14

7. Object Id Class. 15

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

7.2. Oid Class的成员函数列表... 15

7.3. 一些Oid Class的例子... 16

8. OctetStr Class. 19

8.1. 八位字节类... 19

8.2. OctetStr Class的成员函数列表... 19

8.3. 注意... 20

8.4. 一些OctetStr Class的例子... 21

9. TimeTicks Class. 22

9.1. 时间戳类... 22

9.2. TimeTicks Class的成员函数列表... 22

9.3. 注意... 22

9.4. 一些TimeTicks Class的例子... 23

10. Counter32 Class. 24

10.1. 32位计数器类... 24

10.2. Counter32 Class的成员函数列表... 24

10.3. 一些Counter32 Class的例子... 24

11. Gauge32 Class. 26

11.1. 容量类... 26

11.2. Gauge32 Class的成员函数列表... 26

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

12. Counter64 Class. 28

12.1. 64位计数器类... 28

12.2. Counter64 Class的成员函数列表... 28

12.3. 一些的Counter64 Class例子... 29

13. Address Class. 30

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

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

13.3. Address class. 30

13.4. Address Classes及其接口... 30

13.5. IpAddress Class的特点... 32

13.6. GenAddress的特点... 32

13.7. Address Class的有效性... 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. Address Class例子... 34

14. The Variable Binding Class. 36

14.1. Variable Binding Class成员函数列表... 36

14.2. Vb Class的公有成员函数... 37

14.2.1. Vb Class的构造和析构函数... 37

14.2.2. Vb ClassGet Oid / Set Oid成员函数... 38

14.2.3. Vb ClassGet Value / Set Value成员函数... 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. Vb Class成员函数:Get Value. 40

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

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

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

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

14.3. Vb Class例子... 42

15. Pdu Class. 45

15.1. Pdu Class成员函数列表... 45

15.2. Pdu Class的构造和析构... 46

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

15.4. Pdu Class重载操作符... 47

15.5. Pdu Class处理TrapsInforms的成员函数... 47

15.6. 加载Pdu对象... 48

15.7. 加载Pdu对象... 48

15.8. 卸载Pdu对象... 49

16. SnmpMessage Class. 50

17. Target Class. 51

17.1. 抽象的Target51

17.2. Target地址... 51

17.3. 重发机制... 51

17.4. Target Class接口... 51

17.5. CTarget Class (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. Snmp Class. 55

18.1. Snmp Class成员函数列表... 55

18.2. 双效的API56

18.3. Snmp Class的公共成员函数... 57

18.3.1. Snmp Class的构造和析构函数... 57

18.3.2. Snmp Class构造函数... 57

18.3.3. Snmp Class析构函数... 57

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

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

18.3.6. Snmp Class的阻塞方式成员函数: Get Next57

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

18.3.8. Snmp Class的阻塞方式成员函数: Get Bulk. 58

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

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

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

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

18.4.3. Snmp Class的异步成员函数:Get59

18.4.4. Snmp Class的异步成员函数:Set60

18.4.5. Snmp Class的异步成员函数:Get Next60

18.4.6. Snmp Class的异步成员函数:Get Bulk. 60

18.4.7. Snmp Class的异步成员函数: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. Snmp Class的错误消息成员函数... 64

19. 运行模式... 65

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

19.2. Open Systems Foundation (OSF) X11 Motif的运作... 65

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

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

21. 错误状态值... 68

22. Snmp Class例子... 69

22.1. Getting a Single MIB Variable Example. 69

22.2. Getting Multiple MIB Variables Example. 69

22.3. Setting a Single MIB Variable Example. 71

22.4. Setting Multiple MIB Variables Example. 71

22.5. Walking a MIB using Get-Next Example. 72

22.6. Sending a Trap Example. 73

22.7. Receiving Traps Example. 73

23. 参考书目... 75


SNMP++框架的对象模型(Object Modeling Technique)视图

1. 介绍

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

1.1. 什么是SNMP++

SNMP++是一套C++类的集合,它为网络管理应用的开发者提供了SNMP服务。SNMP++并非是现有的SNMP引擎的扩充或者封装。事实上为了效率和方便移植,它只用到了现有的SNMP库里面极少的一部分。SNMP++也不是要取代其他已有的SNMP API,比如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的过程中尽可能少地影响现有代码。SnmpTarget class使之成为了可能。

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

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

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

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

1.2.2. 编程安全的SNMP++

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

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

这包括对SNMP的结构、会话以及传输层的管理。SNMP class被设计成所谓的抽象数据类型(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++的各种特性之前,这里先举个简单的例子来展现它的强大和简单。该例子是从指定的代理端上获取SNMP MIB的系统描述符(System Descriptor object)。包含了创建一个SNMP++会话、获取系统描述符,并打印显示出来的所需的所有代码。其中重发和超时机制已经被SNMP++自动管理了。以下属于SNMP++的代码,采用粗体显示。

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

#include “snmp_pp.h”

#define SYSDESCR “1.3.6.1.2.1.1.1.0” // Object ID for System Descriptor

void get_system_descriptor()

{

int status; // return status

CTarget ctarget( (IpAddress) “10.4.8.5”); // SNMP++ community target

Vb vb( SYSDESCR); // SNMP++ Variable Binding Object

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return; }

//-------[ Invoke a SNMP++ Get ]-------------------------------------------------------

pdu += vb; // add the variable binding to the PDU

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

cout << snmp.error_msg( status);

else {

pdu.get_vb( vb,0); // extract the variable binding from PDU

cout << “System Descriptor = ”<< vb.get_printable_value(); } // print out the value

}; // Thats all!

2.2. 对介绍性例子的分析

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


3. SNMP++特性

3.1. 完整的一套SNMP C++

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++代码。其中只有Snmp Class的实现与不同的目标操作系统有关。如果你的程序中包含了SNMP++的代码,那么导出这部分代码的时候,就可以不做任何修改。

3.6. 自动超时和重发机制

SNMP++提供了自动超时和重发机制,程序员不用去实现超时或重发机制的代码。重发机制是在SnmpTarget Class里面定义的,这就使得每一个目标(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, Get Next, Get Bulk, Set, InformTrap的操作

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

3.12. 通过继承实现重定义

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


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

SNMP++已经在MS-Windows 3.1, MS-Windows For Work Groups 3.11, MS-Windows NT 3.51, and MS-Windows ’95上实现了。

4.1. WinSNMP Version 1.1的使用

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

4.2. 对IPIPX的支持

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

4.3. 对NotificationTrap收发的支持

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

4.4. 与HP OpenView for Windows 兼容

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


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. 与HP OpenView for UNIX 兼容

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


6. SNMP Syntax Classes

SNMP++SNMP Syntax的对象模型(Object Modeling Technique)视图

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

SNMP++ Syntax Class Name

Class Description

SMI or ASN.1 Counter part

SnmpSyntax

Parent of all syntax classes.

No ASN.1 counter part, used for OO structure.

Oid

Object identifier class.

ASN.1 Object Identifier.

OctectStr

Octet string class.

ASN.1 Octet string.

Uint32

Unsigned 32 bit integer class.

SMI unsigned 32 bit integer.

TimeTicks

TimeTicks class.

SMI time ticks.

Counter32

32 bit counter class.

SMI 32 bit counter.

Gauge32

32 bit gauge class.

SMI 32 bit gauge.

Int32

Signed 32 bit integer.

SMI 32 bit signed integer.

Counter64

64 bit counter class.

SMI 64 bit counter.

Address

Abstract address class.

No ASN.1 counter part used for OO structure.

IpAddress

IP address class.

SMI IP address.

UdpAddress

UdpAddress class

SMI IP address with port specification.

IpxAddress

IPX address class.

No ASN.1 or SMI counter part

IpxSockAddress

IPX Address class with socket number.

No ASN.1 or SMI counter part

MacAddress

MAC address class.

SMI counter part

GenAddress

Generic Address

No ASN.1 or SMI counter part.


7. Object Id Class

SNMP++Oid Class的对象模型(Object Modeling Technique)视图

7.1. 对象标识符类

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

7.2. Oid Class的成员函数列表

Oid Class Member Functions

说明

Constructors

Oid::Oid( void);

构造一个空的的Oid

Oid::Oid( const char *dotted_string);

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

Oid::Oid( const Oid &oid);

用已有的Oid构造新的Oid

Oid::Oid( const unsigned long *data, int len);

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

Destructor

Oid::~Oid( );

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

Overloaded Operators

Oid & operator = ( const char *dotted_string);

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

Oid & operator = ( const Oid &oid);

将一个Oid付给另一个Oid

int operator == ( const Oid &lhs, const Oid& rhs);

判断两个Oid是否相等

int operator == ( const Oid& lhs, const char*dotted_string);

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

int operator != ( const Oid &lhs, const Oid& rhs);

判断两个Oid是否不等

int operator != ( const Oid & lhs, const char *dotted_string);

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

int operator < ( const Oid &lhs, const Oid& rhs);

判断一个Oid是否比另一个小

int operator < ( const Oid &lhs, const char *dotted_string);

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

int operator <=( const Oid &lhs,const Oid &rhs);

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

int operator <= ( const Oid &lhs, const char *dotted_string);

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

int operator > ( const Oid &lhs, const Oid &rhs);

判断一个Oid是否比另一个大

int operator > ( const Oid &lhs, const char * dotted_string);

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

int operator >= ( const Oid&lhs, const Oid &rhs);

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

int operator >= ( const Oid &lhs, const char* dotted_string);

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

Oid& operator += ( const char *dotted_string);

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

Oid& operator +=( const unsigned long i);

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

Oid& operator+=( const Oid& oid);

将一个Oid加到另一个Oid后面

unsigned long &operator [ ] ( int position);

访问Oid的一个独立子单元

Output Member Functions

char * get_printable( const unsigned int n);

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

char *get_printable( const unsigned long s, const unsigned long n);

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

char *get_printable();

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

operator char *();

同上

Miscellaneous Member Functions

set_data (const unsigned long *data,const unsigned long n);

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

unsigned long len( );

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

trim( const unsigned long n=1);

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

nCompare( const unsigned long n, const Oid& oid);

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

RnCompare( const unsigned long n, const Oid& oid);

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

int valid( );

返回Oid的有效性

7.3. 一些Oid Class的例子

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

#include “oid.h”

void oid_example()

{

// construct an Oid with a dotted string and print it out

Oid o1("1.2.3.4.5.6.7.8.9.1");

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

// construct an Oid with another Oid and print it out

Oid o2(o1);

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

// trim o2’s last value and print it out

o2.trim(1);

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

// add a 2 value to the end of o2 and print it out

o2+=2;

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

// create a new Oid, o3

Oid o3;

// assign o3 a value and print it out

o3="1.2.3.4.5.6.7.8.9.3";

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

// create o4

Oid o4;

// assign o4 o1’s value

o4=o1;

// trim off o4 by 1

o4.trim(1);

// concat a 4 onto o4 and print it out

o4+=”.4”;

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

// make o5 from o1 and print it out

Oid o5(o1);

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

// compare two not equal oids

if (o1==o2) cout << "O1 EQUALS O2";

else cout << "o1 not equal to o2";

// print out a piece of o1

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

// print out a piece of o1

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

// set o1's last subid

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

cout << "O1 modified = “ << o1.get_printable();

// set o1's 3rd subid

o1[2]=49;

cout << "O1 modified = “ << o1.get_printable();

// get the last subid of 02

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

// get the 3rd subid of 02

cout << "3rd of o2 = “ << o2[2];

// ncompare

if (o1.nCompare(3,o2))

cout << "nCompare o1,o2,3 ==";

else

cout << "nCompare o1,o2,3 !=";

// make an array of oids

Oid oids[30]; int w;

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. OctetStr Class

SNMP++OctetStr Class的对象模型(Object Modeling Technique)视图

8.1. 八位字节类

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

8.2. OctetStr Class的成员函数列表

OctetStr Class Member Functions

说明

Constructors

OctetStr::OctetStr( void);

构造一个空的OctetStr

OctetStr::OctetStr( const char* string);

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

OctetStr::OctetStr( const unsigned char *s, unsigned long int i);

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

OctetStr::OctetStr( const OctetStr &octet);

用已有的OctetStr构造新的OctetStr

Destructor

OctetStr::~OctetStr( );

销毁一个OctetStr

Overloaded Operators

OctetStr& operator = ( const char *string);

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

OctetStr& operator = ( const OctetStr& octet);

将一个OctetStr付给另一个OctetStr

int operator == ( const OctetStr &lhs, const OctetStr &rhs);

判断两个OctetStr对象是否相等

int operator == ( const OctetStr & lhs, const char *string);

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

int operator != ( const OctetStr& lhs, const OctetStr& rhs);

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

int operator != ( const OctetStr& lhs, const char *string);

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

int operator < ( const OctetStr&lhs, const OctetStr& rhs);

判断一个OctetStr是否比另一个小

int operator < ( const OctetStr &lhs, const char * string);

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

int operator <= ( const OctetStr &lhs, const OctetStr &rhs);

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

int operator <= ( const OctetStr &lhs, const char * string);

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

int operator > ( const OctetStr& lhs, const OctetStr &rhs);

判断一个OctetStr是否比另一个大

int operator > ( const OctetStr& lhs, const char * string);

Test if one OctetStr is greater than a char *.

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

int operator >= ( const OctetStr& lhs, const OctetStr &rhs);

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

int operator >= ( const OctetStr& lhs, const char *);

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

OctetStr& operator +=( const char * string);

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

OctetStr& operator +=( const unsigned char c);

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

OctetStr& operator+=( const OctetStr &octetstr);

将两个OctetStr连接在一起

unsigned char& operator[ ] ( int position i);

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

Miscellaneous

void set_data( const unsigned char *s, unsigned long l);

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

int nCompare( const unsigned long n, const OctetStr &o);

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

unsigned long len();

返回一个OctetStr的长度

int valid();

返回一个OctetStr的有效性

unsigned char * 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. 一些OctetStr Class的例子

// Octet Class Examples

#include “octet.h”

void octet_example()

{

OctetStr octet1; // create an invalid un- initialized octet object

OctetStr octet2( “Red Hook Extra Bitter Ale”); // create an octet with a string

OctetStr octet3( octet2); // create an octet with another octet

unsigned char raw_data[50]; // create some raw data

OctetStr octet4( raw_data, 50); // create an OctetStr using unsigned char data

octet1 = “Sierra Nevada Pale Ale”; // assign one octet to another

cout << octet1.get_printable(); // show octet1 as a null terminated string

cout << octet4.get_printable_hex(); // show octet4 as a hex string

cout << (char *) octet1; // same as get_printable()

if ( octet1 == octet2) // compare two octets

cout << “octet1 is equal to octet2”;

octet2 += “WinterFest Ale”; // concat a string to an Octet

if ( octet2 >= octet3)

cout << “octet2 greater than or equal to octet2”;

octet2[4] = ‘b’; // modify an element of an OctetStr using [ ]’s

cout << octet.len(); // print out the length of an OctetStr

unsigned char raw_data[100];

octet1.set_data( raw_data, 100); // set the data of an to unsigned char data

// get the validity of an OctetStr

cout << (octet1.valid() )? “Octet1 is valid” : “Octet1 is Invalid”;

}; // end octet example


9. TimeTicks Class

SNMP++TimeTicks Class的对象模型(Object Modeling Technique)视图


9.1. 时间戳类

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

9.2. TimeTicks Class的成员函数列表

TimeTicks Class Member Functions

说明

Constructors

TimeTicks::TimeTicks( void);

构造一个空的TimeTicks对象

TimeTicks::TimeTicks( const unsigned long i );

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

TimeTicks:;TimeTicks( const TimeTicks &t);

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

Destructor

TimeTicks::~TimeTicks( );

销毁一个TimeTicks对象

Overloaded Operators

TimeTicks& operator =( const TimeTicks &t);

重载赋值操作符

char * get_printable();

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

operator unsigned long();

TimeTicks转换为无符号长整形

9.3. 注意

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

9.4. 一些TimeTicks Class的例子

// TimeTicks Examples

#include “timetick.h”

void timeticks_example()

{

TimeTicks tt; // create an un-initialized timeticks instance

TimeTicks tt1( (unsigned long) 57); // create a timeticks using a number

TimeTicks tt2( tt1); // create a timeticks using another instance

tt = 192; // overloaded assignment to a number

tt2 = tt; // overloaded assignment to another timeticks

cout << tt.get_printable(); // print out in DD days, HH:MM:SS.hh

cout << ( unsigned long) tt; // print out unsigned long int value

}; // end timeticks example


10. Counter32 Class

SNMP++Counter32 Class的对象模型(Object Modeling Technique)视图

10.1. 32位计数器类

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

10.2. Counter32 Class的成员函数列表

Counter32 Class Member Functions

说明

Constructors

Counter32::Counter32( void);

构造一个空的Counter32对象

Counter32::Counter32( const unsigned long i );

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

Counter32::Counter32( const Counter32 &c);

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

Destructor

Counter32::~Counter32( );

销毁一个TimeTicks对象

Overloaded Operators

Counter32& operator = ( const Counter32& c);

重载赋值操作符

char * get_printable();

格式化输出Counter32对象

operator unsigned long( );

Counter32转换为无符号长整形

10.3. 一些Counter32 Class的例子

// Counter Examples

#include “counter.h”

void counter_example()

{

Counter32 ctr; // create an un-initialized counter instance

Counter32 ctr1( (unsigned long) 57); // create a counter using a number

Counter32 ctr2(ctr1); // create a counter using another instance

ctr = 192; // overloaded assignment to a number

ctr1 = ctr; // overloaded assignment to another counter

cout << (unsigned long) ctr; // behave like an unsigned long int

}; // end counter example


11. Gauge32 Class

SNMP++Gauge32 Class的对象模型(Object Modeling Technique)视图


11.1. 容量类

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

11.2. Gauge32 Class的成员函数列表

Gauge32 Class Member Functions

说明

Constructors

Gauge32::Gauge32( void);

构造一个空的Gauge32对象

Gauge32::Gauge32( const unsigned long i );

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

Gauge32::Gauge32( const Gauge32 &g);

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

Destructor

Gauge32::Gauge32( );

销毁一个Gauge32对象

Overloaded Operators

Gauge32& operator = ( const Gauge32 &g);

重载赋值操作符

char * get_printable();

格式化输出Gauge32对象

operator unsigned long( );

Gauge32转换为无符号长整形

11.3. 一些Gauge32的例子

// Gauge Examples

#include “gauge.h”

void gauge_example()

{

Gauge32 gge ; // create an un-initialized Gauge instance

Gauge32gge1( (unsigned long) 57); // create a Gauge using a number

Gauge32 ctr2(ctr1); // create a Gauge using another instance

gge = 192; // overloaded assignment to a number

gge1 = gge; // overloaded assignment to another counter

cout << (unsigned long) gge; // behave like an unsigned long int

}; // end gauge example


12. Counter64 Class

SNMP++Counter64 Class的对象模型(Object Modeling Technique)视图


12.1. 64位计数器类

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

12.2. Counter64 Class的成员函数列表

Counter64 Class Member Functions

说明

Constructors

Counter64::Counter64( void);

构造一个空的Counter64对象

Counter64::Counter64(const unsigned long hi, const unsigned long low );

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

Counter64::Counter64( const Counter64 &ctr64);

拷贝构造函数

Counter64::Counter64( const unsigned long ul);

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

Destructor

Counter64::~Counter64( );

销毁一个Counter64对象

Overloaded Operators

Counter64& operator = ( const Counter64 &ctr64);

将一个Counter64对象付给另一个

Counter64& operator = ( const unsigned long i );

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

Counter64 operator + ( const Counter64 &ctr64);

两个Counter64对象相加

Counter64 operator - ( const Counter64 &ctr64);

两个Counter64对象相减

Counter64 operator * ( const Counter64 &ctr64);

两个Counter64对象相乘

Counter64 operator / ( const Counter64 &ctr64);

两个Counter64对象相除

int operator == ( Counter64 &lhs, Counter64 &rhs);

判断两个Counter64对象是否相等

int operator != ( Counter64 &lhs, Counter64 &rhs);

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

int operator < ( Counter64 &lhs, Counter64 &rhs);

判断一个Counter64是否比另一个小

int operator <= ( Counter64 &lhs, Counter64 &rhs);

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

int operator > ( Counter64 &lhs, Counter64 &rhs);

判断一个Counter64是否比另一个大

int operator >= ( Counter64 &lhs, Counter64 &rhs);

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

Member Functions

unsigned long high();

返回Counter64对象的高位

unsigned long low();

返回Counter64对象的低位

void set_high();

设置Counter64对象的高位

void set_low();

设置Counter64对象的低位

12.3. 一些的Counter64 Class例子

// Counter64 examples

#include “ctr64.h”

void counter64_example()

{

Counter64 c64; // instantiate a 64 bit counter object with no parms

Counter64 my_c64( 100, 100); // instantiate a 64 bit counter with a hi and low value

Counter64 your_c64( my_c64); // instantiate a 64 counter using another 64bit counter

cout << my_c64.high(); // print out the high portion of the c64

cout << my_c64.low(); // print out the low portion of the c64

c64 = my_c64 + your_c64; // overloaded addition

c64 = my_c64 * your_c64; // overloaded multiplication

c64 = my_c64 / your_c64; // overloaded division

c64 = my_c64 - your_c64; // overloaded subtraction

if ( c64 == my_c64) // overloaded equivalence test

cout << “c64 equals my_c64\n”;

if ( c64 != my_c64) // overloaded not equal test

cout << “c64 not equal to my_c64\n”;

if ( c64 < my_c64) // overloaded less than

cout << “c64 less than my_c64\n”;

}; // end Counter64 example


13. Address Class

SNMP++Address Class的对象模型(Object Modeling Technique)视图

13.1. 什么是网络地址类?

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

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

地址类提供了以下好处:自动内存管理、地址确认、移植到任何C++环境、简单易用,及可扩充性。目前的Address class4个子类组成:IpAddress Class, IpxAddress Class, MacAddress classGenAddress class。将来也许会有其他的子类加入,比如IP Next Generation (IPng)

13.3. Address class

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

13.4. Address Classes及其接口

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


Address Class Member Functions

说明

IpAddress Class Constructors

IpAddress::IpAddress( void);

构造一个空的IpAddress对象

IpAddress::IpAddress( const char *string);

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

IpAddress::IpAddress( const IpAddress &ipa);

拷贝构造函数

IPAddress Member Functions

char * friendly_name( int & status);

DNS的名字看起来更友好

UdpAddress Constructors

UdpAddress::UdpAddress( void);

构造一个无效的UdpAddress对象

UdpAddress::UdpAddress( const char *string);

用一个字符串构造一个UdpAddress

UdpAddress::UdpAddress( const UdpAddress &udpa);

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

UdpAddress Member Functions

void UdpAddress:set_port( const unsigned int p);

设置UdpAddress对象的端口号

unsigned int UdpAddress::get_port();

获取UdpAddress对象的端口号

IpxAddress Class Constructors

IpxAddress::IpxAddress( void);

构造一个空的IPX地址

IpxAddress::IpxAddress( const char *string);

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

IpxAddress::IpxAddress( const IpxAddress &ipxa);

拷贝构造函数

IpxSockAddress Constuctors

IpxSockAddress::IpxSockAddress( void);

构造一个空的IpxSockAddress对象

IpxSockAddress::IpxSockAddress( const char *string);

用一个字符串构造一个IpxSockAddress

IpxSockAddress::IpxSockAddress( const IpxSockAddress &ipxs);

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

IpxSockAddress Member Functions

IpxSockAddress::set_socket( const unsigned int s);

从一个IpxSockAddress获得套接字

unsigned int IpxSocketAddress::get_socket();

设置一个IpxSockAddress的套接字

MacAddress Constructors

MacAddress::MacAddress( void);

构造一个空的MacAddress对象

MacAddress::MacAddress( const char * string);

用一个字符串构造一个MacAddress

MacAddress::MacAddress( const MacAddress &mac);

拷贝构造函数

GenAddress Constructors

GenAddress::GenAddress( void);

构造一个无效的GenAddress对象

GenAddress::GenAddress( const char * addr);

用一个字符串构造一个GenAddress

GenAddress::GenAddress( const GenAddress &addr);

拷贝构造函数

Common Member Functions, applicable to all Address classes

int operator == ( const Address &lhs, const Address rhs);

判断两个地址是否相等

int operator != ( const Address &lhs, const Address &rhs);

判断两个地址是否不相等

int operator > ( const Address &lhs, const Address &rhs);

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

int operator >= (const Address &lhs, const Address &rhs);

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

int operator < ( const Address &lhs, const Address &rhs);

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

int operator<=( const Address &lhs, const Address &rhs);

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

int operator == ( const Address &lhs, cosnt char *inaddr);

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

int operator > ( const Address &lhs, const char *inaddr);

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

int operator < ( const Address &lhs, const char *inaddr);

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

virtual int valid( );

判断一个地址的有效性

unsigned char& operator[]( int position);

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

char * get_printable ( );

返回格式化输出的地址

13.5. IpAddress Class的特点

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

13.6. GenAddress的特点

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

GenAddress Examples

GenAddress address1(“10.4.8.5”); // make an IP GenAddress

GenAddress address2(“01020304-10111213141516”); // make an IPX GenAddress

GenAddress address3(“01:02:03:04:05:06”); // make a MAC GenAddress

cout << address3.get_printable(); // print out the GenAddress

if ( !address1.valid()) // check validity

cout << “address1 ! valid”;

13.7. Address Class的有效性

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

Address Class Validation Examples

MacAddress mac;

mac = “01.010a0d”; // invalid MAC address

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

13.8. UdpAddresses和IpxSockAddresses

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

13.8.1. 用UdpAddresses发送请求

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

13.8.2. 用IpxSockAddresses发送请求

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

13.8.3. 用UdpAddressIpxSockAddress接收Notification

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

13.9. 有效的地址格式

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

Valid IP format BNF Grammar XXX.XXX.XXX.XXX

ip-address : ip-token DOT ip-token DOT ip-token DOT ip-token

DOT : ‘.’

ip-token : [0-255]

Valid IPX format BNF GrammarXXXXXXXX:XXXXXXXXXXXX

ipx-address: net-id SEPARATOR mac-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]

Valid MAC format BNF Grammar XX:XX:XX:XX:XX:XX

mac-id: byte_token colon byte_token colon byte_token colon byte_token colon byte_token

byte-token: 1{byte}2

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

colon: ‘:’

13.10.Address Class例子

// address class examples

#include “address.h”

void address_examples()

{

//--------------[ IPAddress construction ]------------------------------------------------------

IpAddress ip1(); // makes an invalid IpAddress object

IpAddress ip2(“10.4.8.5”); // makes a IpAddress verifies dotted format

IpAddress ip3(ip2); // makes an IpAddress using another IpAddress

IpAddress ip4(“trout.rose.hp.com”); // makes an IpAddress does DNS on string

//-------------[ IPX Address construction ]-----------------------------------------------------

IpxAddress ipx1(); // makes an invalid IPX address

IpxAddress ipx2(”); // makes and verifies an IPX address

IpxAddress ipx3( ipx2); // makes an IPX from another IPX

//--------------[ MAC Address construction ]-----------------------------------------------------

MacAddress mac1(); // makes an invalid MAC address

MacAddress mac2(“08:09:12:34:52:12”); // makes and verifies a MAC address

MacAddress mac3( mac2); // makes a MAC from another MAC

//---------------[ Gen Address Construction ]-----------------------------------------------------

GenAddress addr1(“10.4.8.5”);

GenAddress addr2(“01020304:050607080900”);

//--------------[ printing addresses ]----------------------------------------------------------------

cout << (char *) ip2;

cout << (char *) ipx2;

cout << (char *) mac2;

//---------------[ assigning Addresses ]------------------------------------------------------------

ip1 = “15.29.33.10”;

ipx1 = “00000001-080912345212”;

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

//--------------[ comparing Addresses ]----------------------------------------------------------

if ( ip1 == ip2)

cout << “ip1 == ip2”;

if (ipx1 != ipx2)

cout << “ipx1 != ipx2”;

if ( mac1 <= mac2)

cout << “mac1 < mac2”;

//---------------[ modifying an address ]-----------------------------------------------------------

mac1[4] = 15;

cout << mac2[2];

}; // end address examples


14. The Variable Binding Class

SNMP++Variable Binding ( Vb)Class的对象模型(Object Modeling Technique)视图

Variable Binding ( Vb) class SNMP“绑定变量的封装。一个绑定变量是由SNMPobject ID及其SMIvalue组合而成的。用面向对象的概念来看,这只是一个简单的关联关系:一个Vb对象含有一个Oid对象及其SMIvalueVb class允许应用的开发者实例化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类型都与Vb Class兼容。Vb class隐藏了所有内部数据。使用者不需要知道SMIvalue的类型,Oid的内部表示方法,以及其他SNMP相关的结构。如果使用的是标准ANSI C++编译器,Vb class是完全可移植的。

14.1. Variable Binding Class成员函数列表

Variable Binding Class Member Functions

说明

Constructors

Vb( void);

构造一个空的Vb对象

Vb( const Oid &oid);

Oid部分构造一个Vb

Vb( const Vb &vb);

拷贝构造函数

Destructor

~Vb();

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

Set Oid / Get Oid

void set_oid( const Oid &oid);

设置一个VbOid部分

void get_oid( Oid &oid) const;

获得Oid部分

Set Value

void set_value( const SMIValue &val);

设置任一SmiValue

void set_value( const int i);

设置一整形value

void set_value( const long int i);

设置一长整形value

void set_value( const unsigned long int i);

设置一无符号长整形value

void set_value( const char WINFAR * ptr);

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

Get Value

int get_value( SMIValue &val);

获得任一SmiValue

int get_value( int &i);

获得一整形value

int get_value( long int &i);

获得一长整形value

int get_value( unsigned long int &i);

获得一无符号长整形value

int get_value( unsigned char WINFAR * ptr,

unsigned long &len);

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

int get_value( unsigned char WINFAR * ptr,

unsigned long &len,

unsigned long maxlen);

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

int get_value( char WINFAR *ptr);

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

Miscellaneous

SmiUINT32 get_syntax();

返回SMI描述

char *get_printable_value();

返回格式化value

char *get_printable_oid();

返回格式化Oid部分

void set_null();

Vb对象设置一个空value

int valid();

返回一个Vb的有效性

Overloaded Operators

Vb& operator=( const Vb &vb);

把一个Vb付给另一个

14.2. Vb Class的公有成员函数

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

// A Vb object may be constructed with no arguments. In this case, the Oid and

// value portions must be set with subsequent member function calls.

// constructor with no arguments

// makes an Vb, un-initialized

Vb::Vb( void);

14.2.1. Vb Class的构造和析构函数

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

// constructor to initialize the Oid

// makes a Vb with Oid portion initialized

Vb::Vb( const Oid oid);

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

// destructor

// if the Vb has a Oid or an octet string then

// the associated memory needs to be freed

Vb::~Vb();

14.2.2. Vb Class的Get Oid / Set Oid成员函数

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

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

// set value Oid only with another Oid

void Vb::set_oid( const Oid &oid);

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

// get Oid portion

void Vb::get_oid( Oid &oid);

14.2.3. Vb Class的Get Value / Set Value成员函数

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

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

// set the value with an int

void Vb::set_value( const int i);

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

// set the value with a long signed int

void Vb::set_value( const long int i);

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

// set the value with an unsigned long int

void Vb::set_value( const unsigned long int i);

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

// set the value with a 32 bit gauge

void Vb::set_value( const Gauge32 gauge);

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

// set the value with a TimeTicks

void Vb::set_value( const TimeTicks timeticks);

Vb对象设置一Counter32对象作为value,该valueSMI 32 bit counter的映射。

// set value with a 32 bit counter

void Vb::set_value( const Counter32 counter);

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

// set value to a 64 bit counter

void Vb::set_value( const Counter64 c64);

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

// set value for setting an Oid

// creates own space for an Oid which

// needs to be freed when destroyed

void Vb::set_value( const Oid &varoid);

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

// set value on a string

// makes the string an octet

// this must be a null terminates string

void Vb::set_value( const char * ptr);

用一个IP address对象设置Vbvalue部分。该成员函数使用了Address classIP addressSMI value类型的一种。

// set an IPAddress object as a value

void Vb::set_value ( const IpAddress ipaddr);

用一个IPX address对象设置Vbvalue部分。该成员函数使用了Address classIPX address8SMI value类型的一种。

// set an IPXaddress object as a value

void Vb::set_value ( const IpxAddress ipxaddr);

用一个MAC address对象设置Vbvalue部分。该成员函数使用了Address classMAC address8SMI value类型的一种。

// set an MAC address object as a value

void Vb::set_value ( const MacAddress macaddr);

14.2.4. 用一个GenAdress对象设置value

// set an GenAddress object as a value

void Vb::set_value ( const GenAddress genaddr);

14.2.5. 用一个UdpAdress对象设置value

// set an UdpAddress object as a value

void Vb::set_value ( const UdpAddress udpaddr);

14.2.6. 用一个IpxSockAdress对象设置value

// set an IpxSockAddress object as a value

void Vb::set_value ( const IpxSockAddress ipxsockaddr);

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

// set the value portion to a SNMP++ Octet object

void Vb::set_value( const OctetStr octet);

14.2.8. Vb Class成员函数:Get Value

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

Vb对象获得一个整形value

// get value int

// returns 0 on success and value

int Vb::get_value( int &i);

Vb对象获得一个长整形value

// get the signed long int

int Vb::get_value( long int &i);

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

// get the unsigned long int

int Vb::get_value( unsigned long int &i);

// get a Gauge32

int Vb::get_value( Gauge32 &gauge);

Vb对象获得一个Gauge32

Vb对象获得一个TimeTicks

// get a TimeTicks from a Vb

int Vb:get_value( TimeTicks &timeticks);

Vb对象获得一个Counter32

// get a counter from a Vb

int Vb::get_value(Counter32 &counter);

Vb对象获得一个64 bit counter

// get a 64 bit counter

int Vb::get_value( Counter64 &counter64);

Vb对象获得一个Oid对象

// get the Oid value

// free the existing Oid value

// copy in the new Oid value

int Vb::get_value( Oid &varoid);

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

// get a unsigned char string value

// destructive, copies into given ptr of up

// to len length

int Vb::get_value( unsigned char * ptr, unsigned long &len);

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

// get a char * from an octet string

// the user must provide space or

// memory will be stepped on

int Vb::get_value( char *ptr);

Vb对象获得一个IP address对象。IP address是一种Address对象。

// get an IPAddress

int Vb::get_value( IpAddress &ipaddr);

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

// get an IPXAddress

int Vb::get_value( IpxAddress &ipxaddr);

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

// get an MAC address

int Vb::get_value( MacAddress &MACaddr);

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

// get an gen address

int Vb::get_value( GenAddress &genaddr);

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

// get an Udp address

int Vb::get_value( UdpAddress &Udpaddr);

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

// get an IpxSockAddress

int Vb::get_value( IpxSockAddress &IpxSockAddr);

Vb对象获得一个Octet对象

// get an Octet object from a Vb

int Vb::get_value( OctetStr, &octet);

14.2.9. Vb 对象的成员函数:Get Syntax

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

// return the current syntax

// This method violates the OO paradigm but may be useful if

// the caller has a Vb object and does not know what it is.

// This would be useful in the implementation of a browser.

SmiUINT32 get_syntax();

14.2.10.检查Vb对象的有效性

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

// determine if a Vb object is valid

int Vb::valid();

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

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

// overloaded Vb assignment

// assignment to another Vb object overloaded

Vb& operator=( const &Vb vb);

14.2.12.Vb对象的错误信息

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

Vb::get_value() return value

说明

SNMP_CLASS_SUCCESS

成功,返回所请求的值

SNMP_CLASS_INVALID

失败,Vb value没有包含请求的值

14.3. Vb Class例子

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

#include “oid.h”

#include “vb.h”

vb_test()

{

// -------[Ways to construct Vb objects ]-------

// construct a single Vb object

Vb vb1;

// construct a Vb object with an Oid object

// this sets the Oid portion of the Vb

Oid d1(“1.3.6.1.4.12”);

Vb vb2(d1);

// construct a Vb object with a dotted string

Vb vb3( (Oid) “1.2.3.4.5.6”);

// construct an array of ten Vbs

Vb vbs[10];

//------[Ways to set and get the Oid portion of Vb objects ]

// set and get the Oid portion

Oid d2((Oid)“1.2.3.4.5.6”);

vb1.set_oid(d2);

Oid d3;

vb1.get_oid(d3);

if (d2==d3) cout << “They better be equal!!\n”;

Vb ten_vbs[10];

int z;

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

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

//-------[ ways to set and get values ]

// set & get ints

int x,y;

x=5;

vb1.set_value(x);

vb1.get_value(y);

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

// set and get long ints

long int a,b;

a=100;

//-------[ ways to set and get values ]

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

// set & get unsigned long ints

unsigned long int c,d;

c = 1000;

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

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

// set a 64 bit counter

Counter64 c64(1000,1001);

vbs[1].set_value( c64);

// get and set an oid as a value

Oid o1, o2;

o1 = “1.2.3.4.5.6”;

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

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

// set and get an octet string

unsigned char data[4],outdata[4];

unsigned long len,outlen;

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

OctetStr octetstr(data,len);

vbs[3].set_value( octetstr);

vbs[3].get_value( octetstr);

// get & set a string

char beer[80]; char good_beer[80];

strcpy( beer,”Sierra Nevada Pale Ale”);

vbs[4].set_value( beer);

vbs[4].get_value( good_beer);

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

// get and set an ip an address

IpAddress ipaddress1, ipaddress2;

ipaddress1 = “10.4.8.5”;

vbs[5].set_value( ipaddress1);

vbs[5].get_value( ipaddress2);

cout << ipaddress2;

} // end vb example


15. Pdu Class

SNMP++Pdu Class的对象模型(Object Modeling Technique)视图

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

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

15.1. Pdu Class成员函数列表

Pdu Class Member Functions

说明

Constructors

Pdu::Pdu( void);

构造一个空的Pdu

Pdu::Pdu( Vb* pvbs, const int pvb_count);

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

Pdu::Pdu( const Pdu &pdu);

用一个Pdu构造另一个

Member Functions

int get_vblist( Vb* pvbs, const int pvb_count);

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

int set_vblist( Vb* pvbs, const int pvb_count);

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

int get_vb( Vb &vb, const int index);

获取Pdu中一个指定的Vb

int set_vb( Vb &vb, const int index);

Pdu设置一个指定的Vb

int get_vb_count();

获取PduVb的个数

int get_error_status();

获取Pdu的错误状态

int get_error_index();

获取Pdu的错误索引

unsigned long get_request_id();

获取Pdu的请求标示

unsigned short get_type();

获取Pdu的类型

int valid();

判断Pdu的有效性

Int delete_vb( const int position);

删除Pdu指定位置上的Vb

int trim(const int i=1);

删除Pud最后位置上的Vb,默认删除1

Member Functions For Inform and Trap Usage

void set_notify_timestamp( const TimeTicks ×tamp);

trapinformPdu设置时间信息

void get_notify_timestamp( TimeTicks & timestamp);

trapinformPdu获取时间信息

void set_notify_id( const Oid id);

设置trapinformPduID

void get_notify_id( Oid &id);

获取trapinformPduID

void set_notify_enterprise( const Oid &enterprise);

设置trapinformPduenterprise ID

void get_notify_enterprise( Oid & enterprise);

获取trapinformPduenterprise ID

Overloaded Operators 重载操作符

Pdu& operator=( const Pdu &pdu);

将一个Pdu付给另一个

Pdu& operator+=( Vb &vb);

给一个Pdu增加一个Vb

15.2. Pdu Class的构造和析构

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

// constructor, no args

Pdu::Pdu( void);

// constructor with Vbs and count

Pdu::Pdu( Vb *vbs, const int vb_count);

// constructor with another Pdu instance

Pdu::Pdu( const Pdu &pdu);

// destructor

Pdu::~Pdu();

15.3. 访问Pdu的成员函数

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

// extract all the Vbs from a Pdu

int Pdu::get_vblist( Vb* vbs, const int vb_count);

// deposit Vbs to a Pdu

int Pdu::set_vblist( Vb* vbs, const int vb_count);

// get a particular vb

// where index 0 is the 1st vb

int Pdu::get_vb( Vb &vb, const int index);

// set a particular Vb

// where index 0 is the 1st Vb

int Pdu::set_vb( Vb &vb, const int index);

// return the number of Vbs

int Pdu::get_vb_count();

// return the error index

int Pdu::get_error_index();

// get the error status

int Pdu::get_error_status();

// return the request id

unsigned long Pdu::get_request_id();

// get the Pdu type

unsigned short Pdu::get_type();

// return the validity of a Pdu

int Pdu::valid();

15.4. Pdu Class重载操作符

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

// assignment operator for assigning one Pdu to another

Pdu& operator=( const Pdu &pdu);

// append a Vb object to the Pdu’s var bind list

Pdy& operator+=( Vb vb);

15.5. Pdu Class处理TrapsInforms的成员函数

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

// set notify timestamp

void Pdu::set_notify_timestamp( const TimeTicks & timestamp);

// get notify timestamp

void Pdu::get_notify_timestamp( TimeTicks & timestamp);

// set the notify id

void Pdu::set_notify_id( const Oid id);

// get the notify id

void Pdu::get_notify_id( Oid &id);

// set the notify enterprise

void Pdu::set_notify_enterprise( const Oid &enterprise);

// get the notify enterprise

void Pdu::get_notify_enterprise( Oid & enterprise);

15.6. 加载Pdu对象

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

// set notify timestamp

void Pdu::set_notify_timestamp( const TimeTicks & timestamp);

// get notify timestamp

void Pdu::get_notify_timestamp( TimeTicks & timestamp);

// set the notify id

void Pdu::set_notify_id( const Oid id);

// get the notify id

void Pdu::get_notify_id( Oid &id);

// set the notify enterprise

void Pdu::set_notify_enterprise( const Oid &enterprise);

// get the notify enterprise

void Pdu::get_notify_enterprise( Oid & enterprise);

15.7. 加载Pdu对象

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

// example of how to load a Pdu object

void load_pdu_examples()

{

Pdu pdu; // create a Pdu object

Vb vb; // create a Vb object

vb.set_oid( SYSDECR); // set the oid portion of the Vb to System Descriptor

pdu += vb; // loads the Vb to the Pdu

Pdu my_pdu; // create another Pdu object

Vb vbs[5]; // create 5 vbs

pdu.set_vblist( vbs,5); // load all 5 to the pdu

}

15.8. 卸载Pdu对象

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

// example of how to unload a Pdu

void unload_pdu_example( Pdu &pdu)

{

ins staus;

Pdu pdu; // create a Pdu object

Vb vb; // create a Vb object

vb.set_oid( SYSDECR); // set the oid portion of the Vb to System Descriptor

pdu += vb; // loads the Vb to the Pdu

char message[100]; // for the system descriptor printable octet

Snmp snmp( status);

if ( status != SNMP_CLASS_SUCCESS) {

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

return;

}

pdu.get_vb( vb,0); // unload the vb

vb.get_value( message); // pull the message out of the vb

cout << message; // print it out

};


16. SnmpMessage Class

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

SnmpMessage Class Member Functions

说明

Constructors

SnmpMessage::SnmpMessage( void);

构造一个空的SnmpMessage对象

Member Functions

int load( Pdu pdu, OctetStr community,

snmp_version version);

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

int load( unsigned char * data, unsigned long en);

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

int unload( Pdu &pdu, OctetStr &community,

snmp_version &version);

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

unsigned char * data();

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

unsigned long len()

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

int valid();

判断一个SnmpMessage对象的有效性


17. Target Class

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

17.1. 抽象的Target

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

17.2. Target地址

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

17.3. 重发机制

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

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

17.4. Target Class接口

Target Class Member Functions

说明

Constructors

CTarget::CTarget( void);

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

CTarget::CTarget(const Address &address ,

const char *read_community_name,

const char *write_community_name,

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

CTarget( const Address &address

const OctetStr &read_community_name,

const OctetStr &write_community_name);

OctetStr CommunitiesAddress构造一个CTarget

CTarget::CTarget( Address &address);

Address object构造一个CTarget。重发机制的默认值:community names “public”retry=1time_out=1

CTarget::CTarget( const CTarget &target);

拷贝构造函数

Destructor

CTarget::~CTarget();

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

Member Functions

char * get_readcommunity();

返回读权限的community名称

void get_readcommunity( OctetStr& read_community_oct);

获取OctetStr格式的读权限community

void set_readcommunity( const char * get_community);

设置读权限community

void set_readcommunity( const OctetStr& read_community);

用一个OctetStr设置读权限community

char * get_writecommunity();

获取写权限community

void get_writecommunity( OctetStr &write_community_oct);

获取OctetStr格式的写权限community

void set_writecommunity( const char * new_set_community);

设置写权限community

void set_writecommunity( const OctetStr& write_community);

用一个OctetStr设置写权限community

int get_address( GenAddress &address);

获取Address object.

void set_address( Address &address);

设置Address部分

CTarget& operator=( const CTarget& target);

把一个CTarget赋给另一个。

snmp_version get_version();

返回SNMP版本(version1version2

void set_version( const snmp_version v);

设置版本(version1version2

int operator==( const CTarget &lhs, const CTarget &rhs);

比较两个CTargets

Abstract Class Member Functions

int valid();

返回一个Target的有效性

void set_retry( const int r);

设置重发值

int get_retry();

获取重发值

void set_timeout( const unsigned long t);

设置超时值

unsigned long get_timeout();

获取超时值

17.5. CTarget Class (以Community为基础的Target)

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

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

// ----------[ instantiating CTarget Objects ]-----------------------------

// valid complete instantiation

CTarget ct((IpAddress)”10.10.10.10”, // Address

“public”, // read community name

“public”); // write community name

// valid complete using “public” defaults

CTarget ct( (IpAddress) “1.2.3.4”);

// invalid CTarget

CTarget ct;

17.5.2. 修改CTargets

//----[ modifying CTargets ]------------------------------------

ct.set_readcommunity(“private); // modifying the read community

ct.set_writecommunity(“private”); // modifying the write community

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

17.5.3. 访问CTargets

//-----[ Accessing CTarget member variables ]-------------------------

// get the write community name

cout << “Write community” << ct.get_writecommunity();

// get the read community name

cout << “Read community ” << ct.get_readcommunity();

// get the address

GenAddress address;

ct.get_address( address);

// check the validity of a target

if ( ct.valid())

cout << “Target is valid”;

17.5.4. CTargets例子

//------------[CTarget class examples ]-----------------------------------------------------------------

// create a valid CTarget using a GenAddress

CTarget ct( (GenAddress) “10.20.30.40”);

// create a valid CTarget using an IpxAddress

IpxAddress ipxaddress(“01010101-010101010101”);

CTarget my_target( ipxaddress); // use default “public” for communities

// create an invalid CTarget object

CTarget ct; // no construction params therefor invalid

if ( !ct.valid())

cout << “Invalid CTarget instance!”;

// get the read community

cout << “Read Community =” << ct.get_readcommunity();

// get the write community

cout << “Write Community = ” << ct.get_writecommunity();

// modify the get community

ct.set_readcommunity( “pilsner”);

// modify the write community

ct.set_writecommunity(“pale ale”);


18. Snmp Class

SNMP++Snmp Class的对象模型(Object Modeling Technique)视图

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

Snmp class使用简单。它为网络管理应用提供了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(),即陷阱通知的接收。

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

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

18.1. Snmp Class成员函数列表

Snmp Class Member Functions

说明

Constructor

Snmp::Snmp( int &status);

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

Destructor

Snmp::~Snmp( );

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

Member Functions

char * error_msg( const int status);

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

int get( Pdu &pdu, SnmpTarget &target);

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

int set( Pdu &pdu, SnmpTarget &target);

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

int get_next( Pdu &pdu, SnmpTarget &target);

调用阻塞方式的SNMP get next。针对target上的Pdu

int get_bulk( Pdu &pdu, SnmpTarget &target,

const int non_repeaters,

const int max_reps);

调用阻塞方式的SNMP get bulk(但是V2 targets只使用get-next

int inform( Pdu &pdu, SnmpTarget &target);

调用阻塞方式的inform

int get( Pdu &pdu, SnmpTarget &target,

snmp_callback callback,

void * callback_data=0);

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

int set( Pdu &pdu, SnmpTarget &target,

snmp_callback callback,

void * callback_data=0);

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

int get_next( Pdu &pdu, SnmpTarget &target,

snmp_callback callback,

void * callback_data=0);

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

int get_bulk( Pdu &pdu, SnmpTarget &target,

const int non_repeaters,

const int max_reps

snmp_callback callback,

void * callback_data=0);

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

int inform( Pdu &pdu, SnmpTarget &target,

snmp_callback callback,

void * callback_data=0);

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

int trap( Pdu &pdu, SnmpTarget &target);

向指定的target发送一个trap

int notify_register( TargetCollection &targets,

OidCollection &trapids,

snmp_callback callback,

void * callback_data=0);

对接收trapinform的操作注册

int notify_register( TargetCollection &targets,

OidCollection &trapids,

AddressCollection &listen_addresses,

snmp_callback callback,

void * callback_data=0);

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

int notify_unregister();

撤消对接收trapinform的操作注册

int cancel( const unsigned long rid);

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

18.2. 双效的API

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

18.3. Snmp Class的公共成员函数

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

18.3.1. Snmp Class的构造和析构函数

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

18.3.2. Snmp Class构造函数

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

// constructor, blocked SNMP object

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

18.3.3. Snmp Class析构函数

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

// destructor

Snmp::~Snmp();

18.3.4. Snmp Class发送请求的成员函数

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

18.3.5. Snmp Class的阻塞方式成员函数: Get

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

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

int Snmp::get( Pdu &pdu, // Pdu to get

SnmpTarget &target); // specified target

18.3.6. Snmp Class的阻塞方式成员函数: Get Next

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

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

int Snmp::get_next( Pdu &pdu, // Pdu to get next

SnmpTarget &target); // specified target

18.3.7. Snmp Class的阻塞方式成员函数: Set

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

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

int Snmp::set( Pdu &pdu, // Pdu to set

SnmpTarget &target); // specified target

18.3.8. Snmp Class的阻塞方式成员函数: Get Bulk

SNMP++SNMP version 1version 2Target提供了一个获取批量数据的接口。在SNMP version 1中的相应操作对应到成员函数get next

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

int Snmp::get_bulk( Pdu &pdu, // pdu to get_bulk

Target &target, // destination target

const int non_repeaters, // non repeaters

const int max_reps); // maximum reps

18.3.9. Snmp Class的阻塞方式成员函数:Inform

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

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

int Snmp::inform( Pdu &pdu, // pdu to send

SnmpTarget &target); // destination target

为一个Inform指定其Id

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

Inform上指定TimeStamp时间信息

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

18.4. Snmp Class的异步方式成员函数

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

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

typedef void (*snmp_callback)( int, // reason

Snmp*, // session handle

Pdu &, // Pdu passed in

SnmpTarget &, // source target

void * ); // callback data

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()来获得notification id, timestampenterprise

Snmp++ Session, Snmp*

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

Response PDU, Pdu&

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

Target , SnmpTarget&

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

Callback data ,void *

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

18.4.2. 取消一个异步请求

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

//-------------[ cancel a request ]-----------------------------------

int Snmp::cancel( const unsigned long rid);

18.4.3. Snmp Class的异步成员函数:Get

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

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

int Snmp::get ( Pdu &pdu, // Pdu to get async

SnmpTarget &target, // destination target

snmp_callback callback, // async callback

void * callback_data=0); // callback data

18.4.4. Snmp Class的异步成员函数:Set

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

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

int Snmp::set( Pdu &pdu, // Pdu to set async

SnmpTarget &target, // destination target

snmp_callback callback, // async callback

void * callback_data=0); // callback data

18.4.5. Snmp Class的异步成员函数:Get Next

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

//------------------------[ get next async ]-----------------------------

int Snmp::get_next( Pdu &pdu, // Pdu to get_next

SnmpTarget &target, // destination

snmp_callback callback, // async callback

void * callback_data=0); // callback data

18.4.6. Snmp Class的异步成员函数:Get Bulk

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

//------------------------[ get bulk async ]-----------------------------

int Snmp::get_bulk(Pdu &pdu, // Pdu to get_bulk async

Target &target, // destination target

const int non_repeaters, // non repeaters

const int max_reps, // max repetitions

snmp_callback callback, // async callback

void * callback_data=0); // callback data

18.4.7. Snmp Class的异步成员函数:Inform

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

int Snmp::inform( Pdu &pdu, // pdu to send

SnmpTarget &target, // destination target

snmp_callback callback, // callback function

void * callback_data=0); // callback data

18.5. SNMP++通知的方法

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

18.5.1. 发送Trap

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

//-----------------------[ send a trap ]----------------------------------

int Snmp::trap( Pdu &pdu, // Pdu to send

SnmpTarget &target); // destination target

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

Pdu &pdu

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

SnmpTarget &target

发送Trap的目的地

指定一个TrapId

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

SNMP++为通用Trap ID定义的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()来指定trap PDU的时间信息。如果一个Pdu没调用这个成员函数就发送了,那么会使用一个来自SNMP++引擎的时间信息。

18.5.1.2. 指定Trap Enterprise

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

18.5.1.3. 给SNMPv1 Trap指定特殊的Trap

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

18.5.2. 接收Notification

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

//-----------------------[ register to receive traps and informs]-------------------------------------------

// default form listens on all local interfaces using well known port/ socket #’s

int Snmp::notify_register(OidCollection &ids, // types to listen for

TargetCollection &targets, // targets to listen for

snmp_callback callback, // callback to use

void *callback_data=0); // optional callback data

//------------------------[ register to receive traps and informs ]----------------------------------------

// alternate form, AddressCollection allows local listen interface specification

int Snmp::notify_register(OidCollection &ids, // types to listen for

TargetCollection &targets, // targets to listen for

AddressCollection &local_interfaces, // interfaces to listen on

snmp_callback callback, // callback to use

void *callback_data=0); // optional callback data

//-----------------------[ un-register to get traps and informs]------------------------------------------

int Snmp::notify_unregister();

18.5.2.1. 注册TrapInform

每个Snmp class实例可以为它们自己的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。例如:如果我的机器是双网卡的,两个卡都支持IPInternet Protocol)协议,其中一个还支持IPXInternet Exchange Protocol)协议;如果调用基本形式的notify_register(),则会在两个IP接口上使用已知的SNMP trap端口,在IPX接口上使用已知的trap IPX套接字(socket number)。

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

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

AddressCollection Element Behavior Definition

Address Class

Value

说明

IpAddress

Any value except 0.0.0.0

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

IpAddress

0.0.0.0

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

UdpAddress

Any value except 0.0.0.0

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

UdpAddress

0.0.0.0

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

IpxAddress

Any value except 00000000:000000000000

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

IpxAddress

00000000:000000000000

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

IpxSockAddress

Any value except 00000000: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种有序集合的collection classe,共同来收集Oids, TargetsAddresses。所有collection classe操作形式都一样,因为它们是从同样的C++模板类SnmpCollection派生来的。统一的集合操作如下:

Target and Oid Collection Class Member Functions

说明

Constructors

SnmpCollection::SnmpCollection(void);

构造一个空的集合

SnmpCollection::SnmpCollection(const T &t );

用单一元素构造一个集合

Destructors

SnmpCollection::SnmpCollection();

销毁集合,释放所有资源

Member Functions

int size();

返回集合的大小

SnmpCollection & operator += ( T &t);

增加一个元素到集合

SnmpCollection & operator = (SnmpCollection &collection);

将一个集合赋给另一个

T& operator[]( int p);

访问集合中的一个元素

int set_element( const T& i, const int p);

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

int get_element( T& i, const int p);

从集合获取一个元素

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

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

// example of making trap reception filters

// target collection

TargetCollection my_targets;

my_targets += cisco_router;

my_targets += fore_switch;

// Oid collection

OidCollection my_trapids;

my_trapids += coldStart;

my_trapids += warmStart;

// Address collection

AddressCollection my_addresses;

my_addresses += (IpAddress) “10.4.8.5”;

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

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

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

18.6.1. Snmp Class的错误消息成员函数

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

//------------------------[ error message]-----------------------------

char * Snmp::error_msg( const int status); // returns string for provided status


19. 运行模式

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

19.1. Microsoft Windows事件驱动系统的运作

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

19.2. Open Systems Foundation (OSF) X11 Motif的运作

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

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

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

//----------------[ initialize SNMP++ X11 Context ]--------------------------

int SNMPX11Initialize( XtAppContext context);

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

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

SNMPGetFdSets

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

//-------[ get file descriptor set from SNMP++ ]------------------------------------

void SNMPGetFdSets( int &maxfds, // max # of fds represented

fd_set &read_fds, // mask representing read actions

fd_set &write_fds, // mask representing write actions

fd_set &exceptfds); // mask representing exception actions

SNMPGetNextTimeout

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

//---------[ Get the next time-out value ]----------------------------------------------------

unsigned long int SNMPGetNextTimeout( ); // returns value in 1/100 of seconds

SNMPProcessPendingEvents

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

//------[ process pending events ]----------------------------------------------------------

int SNMPProcessPendingEvents();


20. 状态&错误编号

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

SNMP++ General Errors

Value

说明

SNMP_CLASS_SUCCESS

0

成功状态

SNMP_CLASS_ERROR

-1

普通错误

SNMP_CLASS_RESOURCE_UNAVAIL

-2

内存分配失败(Newmalloc

SNMP_CLASS_INTERNAL_ERROR

-3

未知的内部错误

SNMP_CLASS_UNSUPPORTED

-4

不支持的函数

Callback Reasons

SNMP_CLASS_TIMEOUT

-5

明显的请求超时

SNMP_CLASS_ASYNC_RESPONSE

-6

收到应答

SNMP_CLASS_NOTIFICATION

-7

收到notification (trap/inform)

SNMP_CLASS_SESSION_DESTROYED

-8

销毁Snmp对象

Snmp Class Errors

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/inform Oid丢失

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()获取一个额外的错误状态。该值表示的是RFC 1905中实际的SMI PDU错误状态值。这些值可以传进成员函数Snmp::err_msg()以友好的方式描述。

Pdu Error Status Macro

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. Snmp Class例子

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

Program Name and 说明

File Name

SnmpGet, performs SNMP++ get to v1 and v2 agents.

snmpget.cpp

SnmpNext, peforms SNMP++ getNext to v1 and v2 agents.

snmpnext.cpp

SnmpBulk, performs SNMP++ getBulk to v1 and v2 agents.

snmpbulk.cpp

SnmpSet, performs SNMP++ set to v1 and v2 agents.

snmpset.cpp

SnmpTrap, sends v1 or v2 trap to a manager.

snmptrap.cpp

SnmpWalk, walks an agent's MIB using v1 or v2 via GetBulk.

snmpwalk.cpp

22.1. Getting a Single MIB Variable Example

#include “snmp_pp.h”

#define SYSDESCR “1.3.6.1.2.1.1.1.0” // Object ID for System Descriptor

void get_system_descriptor()

{

int status; // return status

CTarget ctarget( (IpAddress) “10.4.8.5”); // SNMP++ v1 target

Vb vb( SYSDESCR); // SNMP++ Variable Binding

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return; }

//-------[ Invoke a SNMP++ Get ]-------------------------------------------------------

pdu += vb; // add the variable binding

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

cout << snmp.error_msg( status);

else {

pdu.get_vb( vb,0); // extract the variable binding

cout << “System Descriptor = ”<< vb.get_printable_value(); } // print out

};

22.2. Getting Multiple MIB Variables Example

#include “snmp_pp.h”

#define SYSDESCR “1.3.6.1.2.1.1.1.0” // Object ID for system descriptor

#define SYSOBJECTID "1.3.6.1.2.1.1.2.0" // Object ID for system object ID

#define SYSUPTIME "1.3.6.1.2.1.1.3.0" // Object ID for system up time

#define SYSCONTACT "1.3.6.1.2.1.1.4.0" // Object ID for system contact

#define SYSNAME "1.3.6.1.2.1.1.5.0" // Object ID for system name

#define SYSLOCATION "1.3.6.1.2.1.1.6.0" // Object ID for system location

#define SYSSERVICES "1.3.6.1.2.1.1.7.0" // Object ID for system services

void get_system_group()

{

int status; // return status

CTarget ctarget( (IpAddress) “10.4.8.5”); // SNMP++ v1 target

Vb vb[7]; // a vb for each object to get

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return; }

//-------[ build up the vbs to get]-----------------------------------------------------------------

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);

//----[ append all the vbs to the pdu ]-----------------------------------------------------

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

pdu += vb[z];

//-------[ Invoke a SNMP++ Get ]-------------------------------------------------------

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

cout << snmp.error_msg( status);

else {

pdu.get_vbs( vb,7); // extract the variable bindings

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

cout << vb[w].get_printable_value() << “\n”; } // print out the value

};

22.3. Setting a Single MIB Variable Example

#include “snmp_pp.h”

#define SYSLOCATION “1.3.6.1.2.1.1.6.0” // Object ID for System location

void set_system_location()

{

int status; // return status

CTarget ctarget( (IpAddress) “10.4.8.5”); // SNMP++ v1 target

Vb vb( SYSLOCATION); // SNMP++ Variable Binding

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return;

}

//-------[ Invoke a SNMP++ Set ]-------------------------------------------------------

vb.set_value(“Upstairs Mezzanine”); // add location string to vb

pdu += vb; // add the variable binding

status = snmp.set( pdu, ctarget);

cout << snmp.error_msg(status);

}


22.4. Setting Multiple MIB Variables Example

#include “snmp_pp.h”

#define SYSCONTACT "1.3.6.1.2.1.1.4.0" // Object ID for system contact

#define SYSNAME "1.3.6.1.2.1.1.5.0" // Object ID for system name

#define SYSLOCATION "1.3.6.1.2.1.1.6.0" // Object ID for system location

void multi_set()

{

int status; // return status

CTarget ctarget( (IpAddress) “10.4.8.5”); // SNMP++ v1 target

Vb vb[3]; // a vb for each object to get

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return; }

//-------[ build up the vbs to get]-----------------------------------------------------------------

vb[0].set_oid( SYSCONTACT);

vb[0].set_value(“Alan Turing”);

vb[1].set_oid( SYSNAME);

vb[1].set_value(“ The Turing Machine”);

vb[2].set_oid( SYSLOCATION );

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

//----[ append all the vbs to the pdu ]-----------------------------------------------------

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

pdu += vb[z];

//-------[ Invoke a SNMP++ Set ]-------------------------------------------------------

status = snmp.set( pdu, ctarget);

cout << snmp.error_msg( status);

}

22.5. Walking a MIB using Get-Next Example

#include “snmp_pp.h” // include snmp++ header file

void mib_walk()

{

int status; // return status

CTarget target( (IpAddress) “10.4.8.5”); // SNMP++ v1 target

Vb vb; // a SNMP++ vb

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return; }

//-------[ set up the first vb ]---------------------------------------------------------------

vb.set_oid(“1”); // get next starting seed

pdu += vb; // add vb to the pdu

status = SNMP_CLASS_SUCCESS;

while ( status == SNMP_CLASS_SUCCESS)

{

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

pdu.get_vb( vb,0); // extract the vb

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

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

pdu.set_vb( vb,0); // use last vb as the next one

}

else

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

}

};

22.6. Sending a Trap Example

#include “snmp_pp.h”

void send_trap()

{

int status; // return status

CTarget target( (IpAddress) “10.4.8.5”); // SNMP++ v1 target

Pdu pdu; // SNMP++ PDU

//-------[ Construct a SNMP++ SNMP Object ]---------------------------------------

Snmp snmp( status); // Create a SNMP++ session

if ( status != SNMP_CLASS_SUCCESS) { // check creation status

cout << snmp.error_msg( status); // if fail, print error string

return; }

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

cout << “ Trap Send Status = “ << snmp.error_msg( status);

};

22.7. Receiving Traps Example

#include “snmp_pp.h”

//-----------------[ trap callback function definition ]-------------------------------------------------------------------

void my_trap_callback ( int reason, // reason

Snmp* session, // session handle

Pdu & pdu, // trap pdu

TimeTicks ×tamp, // timestamp

SnmpTarget &target, // source of the trap

void * cbd) // optional callback data

{

Address *address;

unsigned char get_cummunity[80], set_community[80];

unsigned long timeout;

int retry;

if ( reason == SNMP_CLASS_TRAP) {

target.resolve_to_C( get_community, // get community

set_community, // set community

&address, // address object

timeout, // timeout

retry); // retry

cout << “Trap Received from << address->get_printable() << “Trap Id = “ << trapid.get_printable();

}

else

cout << “Trap Receive Error = “ << session->error_msg( reason);

};

//---------------[ trap receive register ]---------------------------------------------------------------------

Snmp *snmp; // dynamic Snmp object

void trap_register()

{

//----------------[ instantiate an Snmp object, delete when no longer receiving traps ]------------

int status;

snmp = new Snmp( status);

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

cout << “Error constructing Snmp Object\n”;

else

{

//-------[ set up two empty collections, empty denotes receive all ]-------------------------------

TargetCollection targets;

OidCollection trapids;

//------[ invoke the regsiter ]----------------------------------------------------------------------------

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

cout << “ Snmp Trap Register Error “ << snmp->error_msg( status);

}

};


23. 参考书目

[Banker, Mellquist ]

Banker Kim, Mellquist Peter E., SNMP++, Connexions, The Interoperability Report, Volume 9, No. 3, March 1995.

[Comer]

Comer, Douglas E. , Internetworking with TCP/IP, Principles, Protocols and Architecture, Volume I Prentice Hall, 1991.

[Gama, Helm, Johnson, Vlissides]

Erich Gama, Richard Helm , Ralph Johnson, John Vlissides , Design Patterns, Addison Wesley, 1995.

[Meyers]

Meyers, Scott, Effective C++, Addison Wesley, 1994.

[Petzold]

Petzold Charles, Programming MS-Windows, Microsoft Press

[RFC 1452]

J. Case, K. McCloghrie, M. Rose, S. Waldbusser, Coexistence between version 1 and version 2 of the Internet-standard Network Management Framework, May 03, 1993.

[RFC 1442]

J. Case, K. McCloghrie, M. Rose, S. Waldbusser, Structure of Management Information for version 2 of the Simple Network Management Protocol (SNMPv2), May 03 , 1993.

[Rose]

Rose, Marshall T. , The Simple Book, An Introduction to Internet Management , Second Edition, Prentice Hall Series 1994.

[Rumbaugh]

Rumbaugh, James, Object-Oriented Modeling and Design, Prentice Hall, 1991.

[Saks]

Saks, Dan, C++ Programming Guidelines, Thomas Plum & Dan Sacks, 1992.

[Stallings]

Stallings, William, SNMP, SNMPv2 and CMIP The Practical Guide to Network Management Standards, Addison Wesley, 1993.

[Stroustrup]

Stroustrup , Bjarne, The C++ Programming Language, Edition #2 Addison Wesley, 1991.

[WinSNMP]

WinSNMP, Windows SNMP An Open Interface for Programming Network Management Application under Microsoft Windows. Version 1.1.

[WinSockets]

WinSockets, Windows Sockets, An Open Interface for Network Programming under Microsoft Windows.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值