
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. |
| Counter | bit counter class. | SMI 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. |
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的有效性 |
下面的例子展示了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);
}
char msg[100];
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进制格式,进行格式化输出 |
当输出一个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转换为无符号长整形 |
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
