SNMP协议(一)——编码模块设计与实现

       CSDN上高手如云,一直不知道该怎么开始才好,今天终于鼓起勇气将最近的劳动成果记录于此,希望大家多提宝贵意见,多多支持!

       SNMP(Simple Network Management Protocol)简单网络管理协议,是用于网络管理的协议,主要用于网络设备的管理。由于其开源性,一直受大家追捧。又由于其扩展非常简单,只需要编写两个扩展对象的.c和.h文件就可以轻松的将自己的管理信息添加到庞大的MIB树中。也正是因为如此,给它笼罩上了一层神秘的面纱,使人对它接近70M的代码敬而远之!

       事物的两面性约定了它的双重性格:简单、方便但是又占用很多内存空间。这对于其在嵌入式系统中的使用无疑是一个巨大的阻碍!对于我们自己开发的嵌入式系统而言,庞大的MIB树形结构令我们望而生畏。有时候我们只需要使用其中很少一部分东西,却要花费几倍甚至几十倍上百倍的冗余资源,从而大大降低了工作效率!基于此我们提出了《SNMP协议实现》这个课题,通过学习SNMP协议开发出一款适合嵌入式系统的轻量级SNMP协议。目前是基于LINUX系统的,我们的终极目标是无操作系统。

        在该课题中我主要负责的是编码模块,就是对一个SNMP数据包按照基本编码规则BER进行编码。BER(Basic Encoding Rules,基本编码规则),它描述将ASN.1描述的数据类型进行编码的方法。有关BER的细节知识这里不再赘述,可以参考相关文档资料,这里以一个简单的例子来说明。

   例如:      OBJECT IDENTIFIER(对象标识符)在编码时将所包含的每个整数分别按8位组编码,然后按原来各个整数的顺序将它们的编码串接起来。有些整数的表示需要多个8位组,因此,8位组的最高位为延续位,为0时无后续8位组,为1时有后续8位组。对于上述规则的一个特是,OBJECT IDENTIFIER的前两个数字不分别编码,而是组合编码。iso(1)和org(3)的组合用数字43表示,即value1*40+value2。因此Internet的标识符{1 3 6 1}要按{43 6 1}编码。编码结果为:00000110 00000011 00101011 00000110 00000001。第一个8位组表示这是一个tag为Universal 6(即OBJECT IDENTIFIER)的数据类型,第二个8位组表示Value字段有3个8位组,后面的3个8位组分别是整数43, 6和1的编码。
        由上面可以看出,在BER中对每个标识符是按照类型-长度-值的形式来编码的,每个数据都是以8位组的形式来存放的。当数据值或长度值超过8位时,用标志位+数据位的方式进行扩展。改部分在实现的过程中起着举足轻重的作用,在次对其进行详细叙述。对于十进制数与十六进制数的转换代码,网上随处可见这里只给出转换成十六进制数后的编码部分的代码,毕竟这才是本文的中心嘛!

        dec_to_hex(&VarBinds->VariableName[j], tmp);                //将十进制数转换为十六进制数存储到tmp数组中,转换后采用大端模式存储,

        sum = strlen(tmp);

        if((sum*8)/7==0)       //计算转换后的数据长度,当为整数时最后一个字节数据的低七位不需要移位,直接最高位清零就可以表示数据结束了。

        {

                   flag = 1;                               //标志变量

        }

        var[s++] = (tmp[sum-1]>>1 | 0x80;      //第一个字节直接取出高七位转换

        for(sum-=2;sum>=0;sum--)                    //注意:十进制转换为十六进制数之后是采用大端模式存放的

       {

                   offset++;

                   data_high = (unsigned int)tmp[sum+1]&high[offset-1];            //前一位的低位数据在下一字节的高位数据之前

                   data_low = tmp[sum]&low[offset-1];                    //后一位的高位在其前一字节的地位之后

                   data_high = data_high<<(8-offset);                    //分别将高低字节一位后合并,重组为新编码段的数据位

                   data_low =  data_low>>(offset+1);

                   data_low = data_low&remove[offset];               //remove数组用于对移位后的变量值进行修正

                   var[s++] = (data_high+data_low) | 0x80;           //为编码后的数据添加标志位,并存入编码串中

                   if(offset==6)

                  {

                                  var[s++] =( tmp[sum]&0x7f) | 0x80;       //将offset=6时一次完整一位结束,当前数据中低七位独立组成一个编码串,为其添加标志段后存入编码串中

                                  offset = 0;               //将修正下标清零,以便为后续编码做准备

                  }

        }

        if(flag == 1)

       {

                    var[s-1] = var[s-1] & 0x7f;             //数据的最后一个字节独立组成一个编码位,为其添加标志位

       }

       else

       {

                    var[s++] = (tmp[sum+1] & high[offset]) & 0x7f;            //编码串的最后一个字节的部分数据组成编码串,修正并为其添加标志

       }

其中:

char high[6] = {0x01,0x03,0x07,0x0f,0x1f,0x3f};

char low[6] = {0xfc,0xf8,0xf0,0xe0,0xc0,0x80};

char remove[7] = {0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01};

经过以上处理之后,编码后的数据存储在var数组中,而下标s便是编码长度。上述代码看起来似乎比较繁琐,望大家不息赐教!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值