在Snmp++中处理DateAndTime类型数据 选择自 makeitandy 的 Blog

 

DateAndTimeSnmpv2中的一种数据类型,它主要提供了对日期时间的描述。我在使用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 v 1.4.2 _01

hrSWInstalledType:4

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Qt和snmp++实现SNMP操作模块,您可以按照以下步骤进行操作: 1. 安装Qt和snmp++:您需要安装Qt和snmp++库才能开始编写代码。您可以从官方网站下载和安装Qt,并从GitHub上获取snmp++代码并编译。 2. 创建Qt项目:使用Qt Creator创建一个新项目,选择Console Application。 3. 添加snmp++库:将snmp++库添加到Qt项目。在Qt Creator,打开.pro文件并添加以下行: ``` INCLUDEPATH += /path/to/snmp++/headers LIBS += /path/to/snmp++/library ``` 4. 编写代码:在Qt项目编写代码来实现SNMP操作。以下是一个简单的示例代码: ``` #include <iostream> #include "snmp_pp/snmp_pp.h" using namespace std; using namespace Snmp_pp; int main(int argc, char *argv[]) { Snmp snmp(Version::version2c); UdpAddress address("192.168.1.1/161"); CTarget target(address); Pdu pdu; Vb vb; vb.set_oid(Oid("1.3.6.1.2.1.1.1.0")); pdu += vb; snmp.get(pdu, target); if (pdu.get_error_status() != 0) { cout << "Error: " << snmp.error_msg(pdu.get_error_status()) << endl; } else { cout << "Result: " << vb.get_printable_value() << endl; } return 0; } ``` 该代码使用snmp++库来获取远程设备的系统描述符。它创建一个SNMP对象,设置目标地址和PDU,并使用get()方法发送请求。 5. 构建和运行:使用Qt Creator构建和运行项目。如果一切正常,您应该会看到结果输出到控制台。 这只是一个简单的示例,您可以根据需要编写更多的代码来实现您的SNMP操作。希望这能帮助您入门。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值