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. Notification、Trap的收发... 11
3.10. 通过双效的API支持SNMPv1和SNMPv2. 11
3.11. 支持SNMP的Get, Get Next, Get Bulk, Set, Inform和Trap的操作... 11
3.12. 通过继承实现重定义... 11
4. 在Microsoft Windows 系列操作系统上使用SNMP++. 12
4.1. WinSNMP Version 1.1的使用... 12
4.2. 对IP和IPX的支持... 12
4.3. 对Notification、Trap收发的支持... 12
4.4. 与HP OpenView for Windows 兼容... 12
5. 在UNIX上使用SNMP++. 13
5.1. 统一的类的接口... 13
5.2. Windows到UNIX的仿真与移植... 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. UdpAddresses和IpxSockAddresses. 33
13.8.1. 用UdpAddresses发送请求... 33
13.8.2. 用IpxSockAddresses发送请求... 33
13.8.3. 用UdpAddress和IpxSockAddress接收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 Class的Get Oid / Set Oid成员函数... 38
14.2.3. Vb Class的Get 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处理Traps和Informs的成员函数... 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, TargetCollection和AddressCollections过滤... 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. 介绍
目前有许多可以创建网络管理应用的SNMP的API。大多数API都提供了一个很大的函数库,调用这些函数的程序员需要熟悉SNMP内部的工作原理和它的资源管理机制。这些API大多都是平台相关的,导致了SNMP的代码也成了操作系统相关的或者网络系统平台有关的,难以移植。另一方面由于C++有丰富的、可复用的标准类库,用C++开发应用成了目前的主流,然而C++标准类库所缺少的正是一套封装好的处理网络管理的类。如果基于面向对象的方法来进行SNMP网络编程,可以提供以下诸多好处:易用、安全、可移植、能扩展。因此SNMP++灵活有效的解决了其他类似API执行和管理起来都很痛苦的问题。
1.1. 什么是SNMP++
SNMP++是一套C++类的集合,它为网络管理应用的开发者提供了SNMP服务。SNMP++并非是现有的SNMP引擎的扩充或者封装。事实上为了效率和方便移植,它只用到了现有的SNMP库里面极少的一部分。SNMP++也不是要取代其他已有的SNMP API,比如WinSNMP。SNMP++只是通过提供强大灵活的功能,降低管理和执行的复杂性,把面向对象的优点带到了网络编程中。
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对象来执行SNMP的get操作。一旦找到了所需的数据,对应的应答消息就被打印出来。另外,所有的处理错误代码也都包含在内了。
3. SNMP++特性
3.1. 完整的一套SNMP C++类
SNMP++是以一套C++类作为基石的。这些类是:对象描述符(Oid)类、变量绑定(Vb)类、协议数据单元(Pdu)类、Snmp类。并且,其他各种用抽象语法表示(ASN.1)来描述的管理信息结构(SMI),也被抽象成了简单的、面向对象的类型。
3.2. SNMP内存的自动管理
当SNMP++的对象被实例化或销毁的时候, 其相关的类可以自动管理着各种各样的SNMP结构和资源。这就使得应用的开发者不用再担心数据结构和资源的卸载,不然就得为防止内存的崩溃或者泄漏提供有效的保护措施。SNMP++的对象的实例化可以是静态的,也可以是动态的。静态的实例化可以在对象脱离它的作用域时卸载掉;动态分配则需要使用C++的new和delete。在SNMP++内部,有许多被隐藏和保护在公用接口后面的SMI结构。所有的SMI结构都是在内部管理的,程序员不需要定义或管理SMI的结构和它的值。因为在SNMP++内绝大部分地方是不存在C的指针的。
3.3. 简单易用的
由于隐藏并管理了所有SMI结构和它们的值,SNMP++的类使用起来即简单又安全。外部程序员无法破坏到隐藏和保护在作用域后面的东东。
3.4. 强大灵活的
SNMP++提供了强大灵活的功能,降低了管理和执行的复杂性。每个SNMP++对象都通过建立一个会话来和一个代理端联系。即由一个SNMP++的对话类的实例,就能处理所有与特定代理端的连接。另外自动重发和超时控制的机制,为每个SNMP++对象都带来了可靠性。一个应用可能会包含许多SNMP++的对象的实例,每个实例都可能与相同或不同的代理端通话。有了这个功能强大的特性,网络管理程序就可以为每个管理单元建立起不同的会话。另一方面,就算单一的SNMP会话也可以解决问题。例如:一个应用可以通过一个SNMP++对象来处理图形统计,另一个SNMP++对象监控trap,也许还有第三个SNMP++对象用以浏览SNMP。SNMP++自动并行处理了同一时刻来自不同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++允许在多种传输层上(包括IP和IPX)收发trap。而且SNMP++还允许使用非标准的IP端口和IPX套接口来收发trap。
3.10. 通过双效的API支持SNMPv1和SNMPv2
SNMP++的设计可同时支持SNMPv1和SNMPv2的使用。所有API的操作都被设计成了双效的,也即操作是SNMP版本无关的。通过使用SnmpTarget类,与SNMP的版本相关的操作被抽象出来了。
3.11. 支持SNMP的Get, Get Next, Get Bulk, Set, Inform和Trap的操作
SNMP++完整的支持SNMP的6种操作。这6个SNMP++的成员函数使用相同的参数表,也都支持阻塞和非阻塞(异步)方式。
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++的应用兼容。注意,目前HP的MS-Windows设备使用WinSNMP,其他设备不需要使用WinSNMP来进行ANS.1的编码和解码。但那些没有使用WinSNMP的设备也需要与WinSNMP的应用兼容,才能和SNMP++的应用兼容。
4.2. 对IP和IPX的支持
可以通过一个WinSock compliant stack,来实现对IP的操作。同时为了在IPX协议上运行,还需要兼容Novell网络的客户程序和驱动。目前SNMP++已经通过了在广泛多样的协议栈下的运行测试,这些协议栈包括:FTP,Netmanage,LanWorkPlace,MS-WFWG 3.11,以及Windows NT。
4.3. 对Notification、Trap收发的支持
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++面向对象风格的视图。即用于描述SNMP的SMI之ASN.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 class与C++的String class有许多共同之处。如果你熟悉C++的String class或者MFC的CString 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); |
返回一个Oid的n个带点格式的子单元 |
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,可以简单且安全地操作SMI的8位字节。有了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()是专门用来把OctetStr按16进制格式输出的。
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实现了SMI的64 bit counters。64位计数器是在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的动机来源于95年 Interop SNMP++ Birds-of-A-Feather (BOF)上的讨论以及与Hewlett-Packard OpenView程序员的交流。
13.2. 为什么要使用网络地址类?
地址类提供了以下好处:自动内存管理、地址确认、移植到任何C++环境、简单易用,及可扩充性。目前的Address class由4个子类组成:IpAddress Class, IpxAddress Class, MacAddress class和GenAddress 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端口一般用作trap和Notification的接收端口。有些时候需要改变指定的端口号和套接字,UdpAddress class和IpxSockAddress 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. 用UdpAddress和IpxSockAddress接收Notification
UdpAddress和IpxSockAddress还可以通过指定需要修改的端口和套接字来接收notification。即允许应用通过非标准的端口和套接字来接收trap和inform。
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“绑定变量”的封装。一个“绑定变量”是由SNMP的object ID及其SMI的value组合而成的。用面向对象的概念来看,这只是一个简单的关联关系:一个Vb对象含有一个Oid对象及其SMI的value。Vb class允许应用的开发者实例化Vb对象,然后为其分配Oid部分(用Vb::set_value()),并分配value部分(用Vb::get_value())。相反的,Oid和value部分可以通过成员函数Vb::get_oid()和Vb::get_value()提取出来。通过重载了的公有成员函数Vb::set_value()和Vb::get_value(),可以把不同的SMI的value针对“绑定变量”进行“设置”与“取出”。“绑定变量表”在SNMP++中表现为Vb对象的数组。所有的SMI类型都与Vb Class兼容。Vb class隐藏了所有内部数据。使用者不需要知道SMI的value的类型,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); |
设置一个Vb的Oid部分 |
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部分初始化为以参数方式传进来的Oid。Vb对象生成了一个传进来的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).设置Vb的Oid值来的。相反,Oid部分可以通过成员函数Vb::get_oid( Oid &oid)来获取。成员函数get_oid在SNMP的get 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_value,set_value允许获取或设置Vb对象的value部分。这些成员函数通过重载支持对不同类型的获取和设置。隐藏了获取或设置Vb的内部机制,管理了所有内存的分配和释放。这样,程序员就不用担心SMI-value的结构以及它们的管理。通常在SNMP执行了get后,用成员函数get value来获取Vb对象的value。如果希望在SNMP执行set操作时设置Vb的value的话,成员函数set value就有用了。如果获取的value与Vb所包含的不匹配,则成员函数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,该value是SMI 32 bit的映射。
// set the value with a 32 bit gauge
void Vb::set_value( const Gauge32 gauge);
向Vb对象设置一TimeTicks对象作为value,该value是SMI timeticks的映射。
// set the value with a TimeTicks
void Vb::set_value( const TimeTicks timeticks);
向Vb对象设置一Counter32对象作为value,该value是SMI 32 bit counter的映射。
// set value with a 32 bit counter
void Vb::set_value( const Counter32 counter);
向Vb对象设置一Counter64对象作为value,该value用以构成SMI 64 bit counter的32bit的高位部分与低位部分。
// 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位字符串作为SMI的value部分,但是当它是一个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对象设置Vb的value部分。该成员函数使用了Address class。IP address是SMI value类型的一种。
// set an IPAddress object as a value
void Vb::set_value ( const IpAddress ipaddr);
用一个IPX address对象设置Vb的value部分。该成员函数使用了Address class。IPX address是8位SMI value类型的一种。
// set an IPXaddress object as a value
void Vb::set_value ( const IpxAddress ipxaddr);
用一个MAC address对象设置Vb的value部分。该成员函数使用了Address class。MAC address是8位SMI 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 class,Vb 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 class是SMI Protocol Data Unit (PDU)的C++封装。PDU是管理端和代理端进行SNMP通讯的基本概念。通过Pdu class,SNMP++使得对PDU的操作变得简单、安全。Pdu class允许简单的构造、析构,以及在Pdu对象上加载、卸载Vb对象。因为SNMP++是双效的API,所以Pdu class也是抽象化的,并没有包含SNMPv1或者SNMPv2的特征性的信息。所有发出请求的Snmp class成员函数都可以只使用一个Pdu对象。Pdu class作为Snmp class的接口,处理SNMP请求,同时还可作为异步请求和接收notification的回调函数的参数。注意,关于对Vb的存储,Pdu对象是从0开始的(Pdu中第一个vb是Vb #0)。
大多数地方,SNMP++中的所有Pdu对象都是一样的。即,所有的Pdu对象都有同一性(identity)。唯一的例外是当Pdu对象被用作发送otifications , traps和informs的时候。为了支持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(); |
获取Pdu中Vb的个数 |
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); |
为trap或inform的Pdu设置时间信息 |
void get_notify_timestamp( TimeTicks & timestamp); |
从trap或inform的Pdu获取时间信息 |
void set_notify_id( const Oid id); |
设置trap或inform的Pdu的ID |
void get_notify_id( Oid &id); |
获取trap或inform的Pdu的ID |
void set_notify_enterprise( const Oid &enterprise); |
设置trap或inform的Pdu的enterprise ID |
void get_notify_enterprise( Oid & enterprise); |
获取trap或inform的Pdu的enterprise 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处理Traps和Informs的成员函数
当处理notifications, traps和informs的时候,SNMP++提供了成员函数来获取和设置指定的notification value。当使用这些成员函数时,请查阅发送traps和informs的部分。
// 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对象。版本可以是SNMPv1或2。返回错误状态。 |
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。一个target在SNMP通讯中,可以想象成一个代理端的管理层的概念,它由多个网络地址组成。Targets包含了重发和超时机制的信息,还有SNMP协议类型(SNMPv1和SNMPv2)等等。目前已有的Targets唯一的子类是Community-based CTarget。CTarget class可用在SNMPv1和SNMPv2的通讯上,由此可以重用你已有的代码到SNMPv2通讯中,不需要做修改。通过它,还可以使得一个SNMP++会话与某个特定的代理端的属性无关。
17.1. 抽象的Target
SNMP++支持抽象Target的概念。由该抽象Target可以操作所有实际的Target派生类。所有使用Target的SNMP++成员函数接收的都是抽象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=1,time_out=1。 |
CTarget::CTarget(const Address &address , const char *read_community_name, const char *write_community_name, |
用community names和Address object构造一个CTarget。重发机制的默认值:retry=1,time-out =100ms。 |
CTarget( const Address &address const OctetStr &read_community_name, const OctetStr &write_community_name); |
用OctetStr Communities和Address构造一个CTarget |
CTarget::CTarget( Address &address); |
用Address object构造一个CTarget。重发机制的默认值:community names =“public”, retry=1,time_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版本(version1或version2) |
void set_version( const snmp_version v); |
设置版本(version1或version2) |
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 address(Addressclass是个抽象基类,所以可以实现多态操作)。CTarget class使用前提应该是:应用开发者明确地知道代理端所支持的以SNMP community为基础的访问方式,即SNMPv1或SNMPv2。
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 class是SNMP++中最为重要的类。Snmp class封装了SNMP的会话。通过处理与指定代理端的会话,SNMP++实现了对网络管理应用的逻辑绑定。会话所控制的是PDU的构建、分发、接受。其他大多数API需要程序员直接操作会话,也即需要提供可靠的传输机制来控制超时、重发、查重。Snmp class管理了大部分的会话,得到解放的程序员只需要关注于代理端的管理,方便了代码的开发和测试。如果不这样(没有SNMP++),你就只有去设计、实现、测试你自己的SNMP引擎。那么Snmp class是如何管理通信的呢:1、在UDP或IPX连接基础上管理传输层;2、负责打包和解包PDU中的绑定变量;3、分发和接收PDU;4、管理所有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); |
对接收trap和inform的操作注册 |
int notify_register( TargetCollection &targets, OidCollection &trapids, AddressCollection &listen_addresses, snmp_callback callback, void * callback_data=0); |
对接收trap和inform的操作注册,并用AddressCollection指出监听的接口。 |
int notify_unregister(); |
撤消对接收trap和inform的操作注册 |
int cancel( const unsigned long rid); |
取消针对所给请求id的异步请求的等待 |
18.2. 双效的API
所有的Snmp class成员函数都是双效的。这就是说对于SNMP version 1或version 2c,他们可以使用统一的参数表。这解放了程序员,因为程序员不用为了与SNMP version 2的代理端通讯而去修改代码。
18.3. Snmp Class的公共成员函数
通过Snmp Class提供的许多成员函数可以创建、管理、终结一个会话。多个Snmp对象可以在同一时间建立。
18.3.1. Snmp Class的构造和析构函数
Snmp Class的构造和析构函数允许开启和关闭会话。通过构建一个Snmp对象来开启一个Snmp会话。由此可对UDP或IPX套接口实现构建和管理,直到对象被销毁。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 1和version 2的Target提供了一个获取批量数据的接口。在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()来为一个inform的PDU指定其ID。Inform标识符ID代表了其使用的Oid。为了建立Inform ID,可以用需要的Inform ID值来直接建立一个Oid对象,然后用成员函数Pdu::set_notify_id()把一个Pdu加载在其上。反过来,一个inform的ID可以用成员函数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-bulk或inform的应答。用Pdu参数保存实际应答的PDU,用SnmpTarget参数保存发送应答的target。
SNMP_CLASS_TIMEOUT:一个SNMP++请求超时,该请求由target实例提供的超时与重发信息的机制来处理。为了重用,用 Pdu参数保存Pdu请求的原值,用SnmpTarget参数保存target的原值。
SNMP_CLASS_SESSION_DESTROYED:会话被销毁,此时所有正在等待的异步请求都不会完成。
SNMP_CLASS_NOTIFICATION:收到一个notification, trap或inform请求。Pdu对象会保存实际的notify,通过Pdu成员函数Pdu::get_notify_id(), Pdu::get_notify_timestamp()和Pdu::get_notifty_enterprise()来获得notification id, timestamp和enterprise。
Snmp++ Session, Snmp*
该参数保存发送请求的会话的值。由此可以在time-out或get-next情况下实现会话的重用。
Response PDU, Pdu&
该参数为esponse, notifie和trap保存了“应答 Pdu”。当“原因”( reason参数)为“失败”时,Pdu参数保存了“请求 Pdu”的原值。一旦Pdu对象越界,其值就不可得了。
Target , SnmpTarget&
该参数为response, notifie和trap保存了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的工作方式与异步get和set雷同。
//------------------------[ 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的工作方式与异步get和set雷同。
//------------------------[ 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的函数是一个有用的管理程序(manager)API。可用函数与其他管理端进行通讯。
//-----------------------[ 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的目的地
指定一个Trap的Id
Trap Id的指定方式与Inform Id一样。可用成员函数Pdu::set_notify_id()来指定trap PDU的ID。Trap标识符ID在SMI 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值,trapid的Oid应该构造如下:trapid 的最末子id(subid)代表指定的要使用的值;倒数第二个子id应该是零。即,为了指定特殊的Trap值,需要添加两个额外的子id,一个是零、一个是值(“0.X”)。这个约定与规定SNMPv1和SNMPv2trap映射的RFC 1452的描述一致。
18.5.2. 接收Notification
接收SNMP++ trap和inform的时候,允许应用程序使用指定的过滤器来接收trap和inform。不像其他的SNMP操作,trap和inform是在任何可能出现的时候主动发出的。因此informs和traps属于异步的动作。通过SNMP++提供的成员函数,调用者可以指定informs和traps的过滤器。可用informs和traps的类型、来源和目标来过滤informs和traps。
//-----------------------[ 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. 注册Trap和Inform
每个Snmp class实例可以为它们自己的traps / informs注册。也就是说,一个Snmp对象可以有它自己的一套过滤器和回调,当收到的trap或inform满足过滤条件时就会调用。当每个新的呼叫清理了先前的过滤器设置时,成员函数Snmp::notify_register()可能会多次被调用。当调用成员函数Snmp:notify_unregister()或Snmp实例撤消时,相应的接收Trap / inform的会话将会终止。
18.5.2.2. Snmp::notify_register()的基本形式
notification的注册基本形式中包括:notification类型、notification来源、过滤参数、OidCollection和TargetCollection。使用该形式的notify_register()会在所有本地端口上触发notification的监听。所以如果本地机器有多重初始地址,即它会有多重网络接口,所有的接口将会被开启,并使用已知的port / socket来接收notify。例如:如果我的机器是双网卡的,两个卡都支持IP(Internet Protocol)协议,其中一个还支持IPX(Internet Exchange Protocol)协议;如果调用基本形式的notify_register(),则会在两个IP接口上使用已知的SNMP trap端口,在IPX接口上使用已知的trap IPX套接字(socket number)。
18.5.2.3. Snmp::notify_register()的备用形式
作为备用,重载形式的notify_register()可接受一个附加参数,进而允许指定本地接口来监听inform或AddressCollection。AddressCollection参数包含了一组需要监听的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()的过滤功能
当需要过滤时,过滤器的行为如下:如果收到的inform或trap与OidCollection中的id单元(item)一致,并且收到的inform或trap与TargetCollection中的单元一致,则相应的inform / trap会被送到调用者指定的回调中。注意,如果OidCollection为空,则所有的inform都将通过id检查,同样的,如果TargetCollection为空,则所有的inform都将通过Target检查。
18.5.3. 使用OidCollection, TargetCollection和AddressCollections过滤
SNMP++提供了3种有序集合的collection classe,共同来收集Oids, Targets和Addresses。所有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, OidCollection和AddressCollection。要构造这些过滤器,首先得实例化一个集合,然后用重载的操作符“+=”把元素加入其中。
// 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-Windows和X11各种版本上的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)事件。该函数会调用所有与已完成的超时、文件描述符或突出的(outstanding)SNMP消息相关的回调。该函数是非阻塞的,在同一时候它只处理突出的(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 |
内存分配失败(New或malloc) |
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.