9、创建变量捆绑列表,用到的函数是:
HSNMP_VBL SnmpCreateVbl( HSNMP_SESSION session, // handle to the WinSNMP session smiLPCOID name, // pointer to the variable name smiLPCVALUE value // pointer to the value to associate // with the variable ); |
这是一个比较难理解的函数,要对其有深入的理解,你必须对SNMP的数据报格式有所了解,在这里我不能做过多地阐述,可以给你打个比方,好比一个专列火车,他只负责到目的地接人。开始的时候所有车厢是空的,每个车厢标有号码,标志其接的人的特征,好比第一车厢要接所有姓赵的人,第二节车厢要接局以上的领导,等等。车头由司机
驱动着,他当然知道自己的目的地,一路几经周折,终于到达目的地,此时车上还未有一个人,目的地的站长首先要检查该司机的证件和文书,看看他有没有权利来接走这批人,如果没有,就会在第一个车厢内坐上一个本站的通知官,他的责任就是返回告诉源站长官说该司机没有权力接人。如果有,那么站长要看看各节车厢是否符合本站接人的要求,如果符合,就将不同的人送到不同的车厢就坐。如果有改姓的的请求,那么要看本站是否允许,如果允许,就将本站这些符合条件的人改姓。
在这里我们可以把每节车厢看作是不同变量,车厢的空间是用来接收人的,那么具有不同特征的人就是返回数据。这种车厢与其空间就好比一个绑定,SNMP的数据报正如这种方式一次可以有多个绑定。而车厢号就好比对象标志符。当然只有第一个是特殊的,因为他要有车头,所以用SnmpCreateVbl函数,其他的绑定我们要用SnmpSetVb,将其依次连接到前一节车厢上。
好了,由上述,我们可以知道了,该函数的第一个参数是第二步返回的会话句炳,而其他两个参数开始时就可以置为空了。该函数返回一个绑定列表句炳。
10、追加绑定列表,用到的函数是:
SNMPAPI_STATUS SnmpSetVb( HSNMP_VBL vbl, // handle to the variable bindings list smiUINT32 index, // position of the variable binding entry // in the list smiLPCOID name, // pointer to the variable name portion // of the entry smiLPCVALUE value // pointer to the variable value portion // of the entry ); |
我们可以看到这个函数的后两个参数与SnmpCreateVbl相同,也就是车厢与空间的绑定。第一个参数是HSNMP_VBL,一个绑定列表句炳,这也可以理解,因为我们已经创建了绑定列表,第二个参数是变量绑定索引,想一想,这么多节车厢,总的有个顺序吧,别忙,你会提出一个显而易见的问题,如果我只创建了头一个绑定列表,我想在向其追加其他的绑定列表,那么该索引值会有什么用呢?我完全可以顺序加进去啊。就像一个队列似的。完全正确!实际上该函数也是这样实现的,当我们要追加变量绑定时,我们须将该索引值置为0。该索引值只是在我们实现诸如set命令时才用到,这将在下文中叙述。
一且进行得很顺利,不过如果你没有进行过SNMP编程的话,你会对其中两个结构感到迷惑,一个是smiLPCOID,还有就是smiLPCVALUE,别急,先看第一个结构,你会发现有一个英文组合你会很熟悉,因为我在前文介绍过他,就是smiLPCOID中的OID,对了,他的意思是对象标志符,LP如果你常用VC编程也会知道他多数是一个指针了。是了,他就是一个指向smiOID的指针类型。让我们看看他的内部构造:
typedef struct { smiUINT32 len; // number of array elements smiLPUINT32 ptr; // pointer to an array of subidentifiers } smiOID, *smiLPOID; |
有两个类型,第一个用来指定他有多少个数字,第二个则指向一个一维数组,举个例子,如果一个对象标志符是1.3.6.1.2.1.1.1,那么len应该为8,ptr应该指向一个数组,该数组的元素由1,3,6,1,2,1,1,1组成,好像“.”没有了,正确,因为在SNMP中就要用到这样的结构,你会想,怎样才能构造这样一个结构呢?很简单,SNMP的API函数给我们提供了方便,你可以定义一个字符串如"1.3.6.1.2.1.1.1",用
SNMPAPI_STATUS SnmpStrToOid( LPCSTR string, // string object identifier to convert smiLPOID dstOID // object identifier internal representation ); |
函数来进行转换,看看其中两个参数,是不是很吻合的对应啊。当然,这种转换时可逆的,你可以用SnmpOidToStr来进行,具体可以查一下MSDN。
下面讲一讲smiLPCVALUE,由上面的推理,你一定可以得出他是一个指向smiVALUE的指针类型。让我们来看看smiVALUE结构,这个结构比较复杂,我试图讲得清楚一些。
typedef struct { // smiVALUE portion of VarBind smiUINT32 syntax; // Insert SNMP_SYNTAX_<type> union { smiINT sNumber; // SNMP_SYNTAX_INT // SNMP_SYNTAX_INT32 smiUINT32 uNumber; // SNMP_SYNTAX_UINT32 // SNMP_SYNTAX_CNTR32 // SNMP_SYNTAX_GAUGE32 // SNMP_SYNTAX_TIMETICKS smiCNTR64 hNumber; // SNMP_SYNTAX_CNTR64 smiOCTETS string; // SNMP_SYNTAX_OCTETS // SNMP_SYNTAX_BITS // SNMP_SYNTAX_OPAQUE // SNMP_SYNTAX_IPADDR // SNMP_SYNTAX_NSAPADDR smiOID oid; // SNMP_SYNTAX_OID smiBYTE empty; // SNMP_SYNTAX_NULL // SNMP_SYNTAX_NOSUCHOBJECT // SNMP_SYNTAX_NOSUCHINSTANCE // SNMP_SYNTAX_ENDOFMIBVIEW } value; // union } smiVALUE, *smiLPVALUE; |
从整体上看,该结构有两个类型构成,一个是smiUINT32 syntax; 另一个看上去挺复杂,但仔细看却是一个共同体类型,是了,那么它们之间有什么联系呢?我们可以想象一下,一个车厢只接收一种类型的数据,该类型的数据又会有他自己的值,如此就好解释了,syntax就是用来标志数据类型的,当该类型确定后,我们就从union中找到与它相对应的值value。SNMP中这种
设计是很巧妙的。从上面这个结构我们也就了解到在SNMP中所用到的基本数据类型了,也就是union中所列出的,在这提一下,通常有关
网络设备描述的值都是smiOCTETS类型。
再来看看我们已完成的工作,到目前为止我们已经有四个句炳了,1。会话句炳,2。实体句炳,3。上下文句炳,4。绑定列表句炳。还介绍了两个结构。这两个结构全和变量绑定列表相关,现在火车的车厢和空间已经有了,车头也有了,还差给他装上轮子,找一个好司机了,需要他记住自己的使命。
