在Snmp++中处理DateAndTime类型数据

类别:编程语言 点击:0 评论:0 推荐:

DateAndTime是Snmpv2中的一种数据类型,它主要提供了对日期时间的描述。我在使用Snmp++开发包时,发现其不提供对DateAndTime类型的支持,而有时又需要用到该类型,于是,自己写了一个DateTime类扩展Snmp++。通过该类可以实现对DateAndTime类型的格式化,并且可以方便地提取各时间项。下面就对该类进行一下介绍。

要实现DateTime类,首先要要理解DateAndTime类型的定义。下面是RFC中对DateAndTime的定义:

DateAndTime ::= OCTET STRING (SIZE (8 | 11))

   --        A date-time specification for the local time of day.

   --        This data type is intended to provide a consistent

   --        method of reporting date information.

   --

   --            field  octets  contents                  range

   --            _____  ______  ________                  _____

   --              1      1-2   year                      0..65536

   --                           (in network byte order)

   --              2       3    month                     1..12

   --              3       4    day                       1..31

   --              4       5    hour                      0..23

   --              5       6    minutes                   0..59

   --              6       7    seconds                   0..60

   --                           (use 60 for leap-second)

   --              7       8    deci-seconds              0..9

   --              8       9    direction from UTC        "+" / "-"

   --                           (in ascii notation)

   --              9      10    hours from UTC            0..11

   --             10      11    minutes from UTC          0..59

   --

   --            Note that if only local time is known, then

   --            timezone information (fields 8-10) is not present.

由定义可见,DateAndTime仍然是OCTET STRING类型的数据,只是对每个字节进行了具体的定义。比如前两个字节表示年,第五个字节表示小时等。所以如果某个开发包中没有DateAndTime类型,那么大可以用Octet类型去代替。但是这样做得到的只是一些无意义的乱码而已。因此,实现的关键就在于按照定义对特殊的Octet数据进行正确的解析。

既然DateAndTime也是Octet String,我们就通过Snmp++的OctetStr类继承得到类DateTime。这样,提取数据等底层工作都可以交给Snmp++,它会按照Octet String的得到方法原始数据。在Snmp++中,所有的SMI数据类型都有一个get_printable函数,它返回一个格式化好的字符串供程序打印输出等。该函数是一个虚函数,各个具体的类有不同的实现方法。如果我们直接调用OctetStr类的get_printable函数来输出DateAndTime类型数据,就会像前面所述的一样得到乱码,因此我们要重写该函数。另外,每个SMI数据类型类还有一个get_syntax函数,它返回一个32位整数,表示当前的数据类型的代码,它也是一个虚函数,同样需要重写。

下面我们来看一看DateTime类的定义:

 

#include "../snmp_include/octet.h"

 

#define sNMP_SYNTAX_DATETIME   (aSN_APPLICATION | aSN_PRIMITIVE | 0x09)

 

/*this class implement the DateAndTime type defined in Snmpv2,

  the oringinal snmp++ doesn't directly support this type*/

class DateTime:public OctetStr{

   char format_str[128];   //保存格式化过后的时间字符串

   int year;

   int month;

   int day;

   int hour;

   int minute;

   int second;

   int msecond;

public:    

   int get_year();

   int get_month();

   int get_day();

   int get_hour();

   int get_minute();

   int get_second();

   int get_msecond();

   void format();

   //the virtual function overwrite get_printble in class OctetStr

   SmiUINT32 get_syntax();

   char  *get_printable();

};

其中format_str保存格式化过后的字符串,以后调用get_printable函数时都会返回这个字符串。其余数据项按其名字即知表示年月等时间项,并且都有一个对应的get函数来得到其值。#define sNMP_SYNTAX_DATETIME (aSN_APPLICATION | aSN_PRIMITIVE | 0x09)是对这个数据类型的代码的定义,一般来说,应该将这一行放在smi.h头文件中。定义了这个数字过后,就要修改get_syntax()函数,将其重载为:

SmiUINT32 DateTime::get_syntax()

{

   return sNMP_SYNTAX_DATETIME;

}

在成员函数中,最重要的是format()函数,它将实现各时间项数据的解析和对原始字符串的格式化。下面是其实现:

void DateTime::format(){
           //以下为提取时间数据

   char *pbuf=(char *)this->data();

   char buf[10];

   for(int i=0; i<10; i++){

      buf[i]=0;

   }

   strcpy( buf ,pbuf);

   year=buf[0]*256+256+buf[1];

   month=buf[2];

   day=buf[3];

   hour=buf[4];

   minute=buf[5];

   second=buf[6];

   msecond=buf[7];

  
          //以下为格式化字符串

   int index=3;

   int temp=year;

   for(; index>=0; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[4]='-';

   index=6;

   temp=month;

   for(; index>=5; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[7]='-';

   index=9;

   temp=day;

   for(; index>=8; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[10]=',';

   index=12;

   temp=hour;

   for(; index>=11; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[13]=':';

   index=15;

   temp=minute;

   for(; index>=14; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[16]=':';

   index=18;

   temp=second;

   for(; index>=17; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[19]='.';

   index=21;

   temp=msecond;

   for(; index>=20; index--){

      format_str[index]=48+(temp-temp/10*10);

      temp/=10;

   }

   format_str[22]=0; 

}

在处理过程中,由于各位字节就是一个数字,所以处理也比较简单,只需直接将对应字节赋值给其所表示的数字即可,比如要得到月就用month=buf[2]。只有处理年的时候稍有不同,因为年是由两个字节表示,所以要用高位字节乘256再加低位字节,处理语句为year=buf[0]*256+256+buf[1]。

标准的时间输出格式应该为YYYY-MM-DD,HH:MM:SS.MM形式,因此经过处理过后的format_str字符串中将存储这种格式的时间字符串。具体将数字转化为字符的代码见上面,这里就不再解释了。要说明的是对于这段代码可以用数字字符串转换函数将其简化。

处理完数据后,就可以重载get_printable()函数了,因为不能确定每次调用该函数时数据是否已经更新,所以在返回值之前都要先调用format格式化一下。

char  *DateTime::get_printable()

{

   format();

   return format_str;

}

由此,我们就得到了一个比较完整的DateTime类。经测试,证明能正确运行。比如下面是我得到的某台机器上软件安装表的一行数据:

hrSWInstalledIndex:41

hrSWInstalledName:Java 2 SDK, SE v1.4.2_01

hrSWInstalledType:4

hrSWInstalledDate:2004-07-01,19:29:50.00

可见,使用该类就可以正确地解析DateAndTime类型的数据。通过扩展,我们还可以生成更多的Snmp++不直接支持的数据类型,这也是面向对象技术中继承特性带给我们的好处之一吧。

本文地址:http://com.8s8s.com/it/it26419.htm