从我接触SNMP的过程中,我发现在我们这块领域内存在两个很大的缺陷,就是真正有用的文档太少了更别说中文的了,从最开始写Snmp管理端的时候,对动态加载MIB那一块就感觉资料非常少,不得以自己一行一行分析Mib文件,研究ASN.1,自己写了个Delphi版的mib Parser。到我们想去动手自己写snmp协议库的时候,资料更是少!这是其一!其二:目前大部分做这方面开发的朋友,都是在用SNMP++,NET-SNMP,它们的代码其实都让人感觉有点发怵,更有胜者,看看adventnet它的Agent Toolkit C Edition,它写的封装snmp协议库(C版本)的源代码,那更让人却步!
其实说到底SNMP Agent的实现机理和内部框架是比较清晰和容易掌握的。现把我在开发CSnmp的过程中的系统架构和实现难点总结出来于大家分享,希望能对那些不仅仅是用
已有的SNMP库开发网络应用管理程序的朋友有一点帮助。
首先用非常一句话概括CSnmp的功能,它是一个实现了snmpV 2c 、snmpV3标准,并打开705端口实现AgentX(RFC 2741)大部分重要PDU的AGENT,并提供开发支持AgentX
协议的SubAgent的开发API(目前只提供JAVA版本的,紧接着下一步立刻提供C版本的API)。
CSnmp的架构如下:管理端<-――>MasterAgent<―――>SubAgent
1. MasterAgent打开两个端口161, 705。161负责接受从管理端来的请求(GetPDU, GetNextPDU, GetBulkPDU等),705负责向每个subAgent发送AgentXGetPDU, AgentXGetNext, AgnetXGetBulk请求,当然这些请求是按照AgentX协议的标准来封装的(AgentX协议相对标准的SNMP来说较为简单),同时705端口还负责接受从SubAgent处来的请求,比如说agentx-Open-PDU、agentx-Register-PDU、agentx-Notify-PDU等。
2. 正因为打开了两个端口,那么就应该在软件实现中至少有一个HashMap(暂取名为Map1)负责存储从管理端来的request。这个HashMap的Index是向subAgent发送的请求包中的transactionID。
3.当subAgent接受到从MasterAgent来的请求后,解AgentXPDU包,看到底是做什么的,并进行与之相应的处理,把产生的结果按The agentx-Response-PDU的要求打包,发送给MasterAgent。
4.MasterAgent从705端口接受到,开始发出请求的相应,解开这个AgentX Response PDU包,从解包结果中把transactionID取出来,到刚才的Map1中根据transactionID去找到开始从Manager(管理端)进来的请求,并根据该请求把subAgent返回的值按SNMP协议打包,发还给Manager,从而完成了一次完整的交互过程。
下面,就大家非常关心的 Mib 问题,从实现层面上来做一分析。 Mib 信息分别在 SubAgent 和 MasterAgent 中都要存储。 Mib 的存储由两种数据结构共同合作来实现,一个是 HashMap( 暂取名为 mibMap) ,一个是 Vector (暂取名为 mibVector )。 mibMap 是为了快速搜索由 subAgent 注册的 mib Subtree (“注册”:就是 subAgent 告诉 MasterAgent 说该 mib 节点下的所有子节点你都可以到我这个 subAgent 去找)。而 mibVector 则是为了方便的实现 getNext 这一操作。有了这个 mibVector ,所有在 MasterAgent 中被 subAgents 注册的 mib 节点都是按照“字典“顺序排序的。其实,每个从 Manager 发给 MasterAgent 的请求,在解包后的第一步就是看该请求中的 mib OID 是不是在 mibMap 中,有的话接着进行下面的操作,没有的话直接返回管理端,并报以相应的错误。