基于C#特性及反射实现SNMP协议OID与对象属性映射的方案
一、背景
网管服务器(NMS)通过SNMP Trap接收SNMP Agent主动上送的网管设备信息(一次上送多个设备信息,不同类型信息使用不同OID标记),NMS需要将接收的OID信息映射到对应的设备对象属性。
下图为NMS与SNMP Agent间的通信:

二、协议
NMS与SNMP Agent约定设备Trap协议:
MIB节点定义:设备信息以1.3.6.1.4.1.10000开头,记作x,则x.1表示1.3.6.1.4.1.10000.1。
设备信息OID说明见表格:
| OID | 类型 | 描述 |
| x.1 | octet string | 设备名称 |
| x.2 | octet string | 设备状态 |
三、设计实现
设计设备类:
class Device { public string Name {get;set;}
public string Status {get;set;} }
问题:NMS接收SNMP Agent设备信息后,如何将OID转化为Device对应的属性?即OID为x.1的值存储到Device类的Name属性。
思路:如果Device类的属性与OID有映射关系即可实现。
沿着这个思路容易想到给属性标记特性,每个特性传入不同的OID标记,然后通过反射查找匹配的OID属性。
新设计一个特性类,用来给设备属性标记映射的OID:
[System.AttributeUsage(System.AttributeTargets.Property, Inherited = false, AllowMultiple = false)] class OidAttribute : Attribute { readonly string oid; public OidAttribute(string oid) { this.oid = oid; } public string Oid { get { return oid; } } }
于是最初的设备类变为:
class Device { [Oid("1.3.6.1.4.1.10000.1")] public string Name {get;set;} [Oid("1.3.6.1.4.1.10000.2")] public string Status {get;set;} }
NMS与SNMP Agent通信、接收SNMP Trap并组织数据环节非本文讲述重点,故省略,该环节最终整理出的数据结构为Dictionary<string,string>,该结构包含了设备OID及对应的值。
接下来实现OID数据与设备属性之间的映射赋值:
public T SetOidProperty<T>(T t,Dictionary<string, string> oids) { Type type = t.GetType(); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in properties) { var attributes = property.GetCustomAttributes(typeof(OidAttribute), true); if (attributes != null && attributes.Length > 0) { var attribute = attributes[0] as OidAttribute; if (oids.ContainsKey(attribute.Oid)) //属性标记的OID与接收OID一致 {
//将接收到的OID值赋值给匹配的对象属性 property.SetValue(t, oids[attribute.Oid]); } } } return t; }
上述代码实现了将OID与对象属性之间的映射,通过反射及泛型实现有诸多优点:
1、设备OID发生变化后,设备属性容易扩展,例如设备信息要求增加一个采集项(CPU使用率),只需要在Device中增加一个对应CPU使用率的属性并标记为使用OidAttribute即可。
2、使用泛型实现了算法复用,除了设备类,诸如设备报警类也可以实现复用。
四、补充说明
1、SNMP Agent使用Trap上送设备信息,模拟工具使用iReasoning MIB Browser,本文使用的个人免费版:MIB Browser Free Personal Edition。
2、NMS接收SNMP Trap使用SnmpSharpNet库。
写写画画,神奇的事情发生了
浙公网安备 33010602011771号