一、SNMP
SNMP是基于TCP/IP协议族的网络管理标准,是一种应用层协议,是目前网络中应用最广泛的网络管理协议。SNMP使用客户/服务器模型,对应着管理站和代理站。SNMP的核心是帮助管理员简化一些支持SNMP设备设置的操作(也包括这些信息的收集),提供从网络上的设备中手机网络管理信息的方法。例如,使用SNMP可以关闭路由器的一个端口,也可以查看以太网端口的工作速率。SNMP还可以监控交换机的温度,在出现过高现象进行报警。SNMP通常和管理路由器相关联,实际上SNMP可以用于管理很多类型的设备。
二、基于TCP/IP网络管理的网络管理模块的关键部分:
SNMP就是用来规定NMS和Agent之间是如何传递信息管理的应用层协议。
1、网管站(NMS)
网管站通常是一个独立的设备,可以是一般台式机也可以是一台高性能服务器,用作网络管理者进行网络管理的用户接口。基站上必须装有管理软件,管理员可以使用的用户接口和从MIB取得信息的数据库。同时为了进行网络管理他应该具有将管理命令发出基站的能力。对网络设备发出各种查询报文,并接受来自北管设备的响应以及陷阱报文,将结果显示出来。
2、代理站(Agent)
代理站是被管对象,是一种网络设备,如路由器、主机等,是一在被管网络设备上运行的软件模块,设备出厂时已经开发好并烧录如设备上,这些设备必须能接收管理站发来的信息,他们的状态也必须可以有管理站监视。负责接收、处理来自网管站的请求报文,然后从设备上其他协议模块中取得管理变量的数值,形成响应报文,发送给NMS。在一些特殊的情况下,如接口状态发生改变等时候,主动给NMS发送陷阱报文。
3、管理信息库(MIB)
MIB是对象的集合,在其上定义了网络设备的各项参数,通过对这些参数的读取和设置来实现对网络设备的监控。SNMP的管理信息库采用和域名系统DNS相似的树形结构,它的根在最上面,跟没有名字。
MIB树形结构
OID由树上一系列证书组成,整数间用.分开。例如,OID{1.3.6.1.2.1.1}就表示节点mib-2的子对象system,这个对象内保存着与网络设备有关系的系统信息。
4、管理信息结构(SMI)
用于定义通过网络管理协议可以访问对象的规则。定义在MIB中使用的数据类型以及网络资源在MIN中的名称或表示。
5、SNMP
SNMP为应用层协议,是TCP/IP协议族的一部分。通过用户数据协议(UDP)来操作。在分立的管理站中,管理者进场对位于管理站中心的MIB的访问进行控制,并提供网络管理接口。管理者进程通过SNMP完成网络管理。SNMP消息去全部通过UPD端口161接收,只有trap信息采用UDP的162端口。
三、SNMP基本原理
在SNMP中使用UDP协议,可能发生管理进程和代理进程之间的数据包丢失的情况,因此一定要有超时和重传机制。信息交换有2中触发方式:一个是管理者以轮询的方式,另一个是代理进程发送trap报文。
sNMP的5中基本操作:
GET-REQUEST:从某变量中取值(NSM发送给Agent)
GET-NEXT_REQUEST:从表格中去下一个值(NSM发送给Agent)
GET-RESPONSE:响应操作(Agent发送给NMS)
SET-REQUEST:把数值存入具体变量,可以对网络进行远程配置,包括备名、设备属性等,由管理站设置代理的管理信息库的对象值(NSM发送给Agent)
Trap:报告事件信息(Agent发送给NMS)
NMS周期性的发送GET-REQUEST、GET-NEXT_REQUEST报文来轮询各个Agent,获取各个MIB中的管理信息,NMS也接收Agent发送来的Trap报文,并记录在数据库中。当Agent接收到NMS发送的Get报文后,将根据请求的内容从本地MIB中提取所需的信息,并以GET-RESPONSE报文方式将结果回送给NMS。
NMS必须在162端口上侦听Trap消息,并通过161端口发送GET-REQUEST,GET-NET_REQUEST,SET-REQUEST。Agent必须在161端口上侦听侦听GET-REQUEST,GET-NEXT_REQUEST,SET-REQUEST消息的到来,通过162端口发送Trap,161端口发送GET-RESPONSE。
四、SNMP++
SNMP++是HP公司开发的,开源的,用于SNMP编程的C++库,把WinSNMP的API函数封装成相关的C++类,面向对象化,简化了SNMP开发的复杂性和开发难度。
SNMP++封装了相关的类:
1、SNMP类
SNMP类是SNMP++中最重要的类,它封装了SNMP会话和基本的SNMP协议操作(get、getnext、set、trap、getbulk、inform)过程。SNMP类管理通信:1、在UDP或IPX连接基础上管理传输层;2、负责打包盒解包PDU中的绑定变量;分发和接收PDU;4、管理所有SNMP所需的资源。
2、Address类
所有地址类都派生自这个抽象基类,通过使用虚成员函数,提供了公共接口,可以使用公共接口调用各个不同地址类的函数。如IP地址,UDP地址。
3、Oid类
Oid类封装了SMI的对象标识。通过构造函数和成员函数可以定义和操作OID对象。
4、Vb类
variable Binding class是SNMP“绑定变量”的封装。一个绑定变量时由SNMP的object ID和SMI的value组合而成的。即:一个Vb对象含有一个oid对象及其SMI的value。可以通过成员函数对绑定变量进行设置和取出。
5、Pdu类
Pdu类是SNMP++类库对5中协议数据单元PDU做的封装。是管理端和代理端进行SNMP通讯的基本概念。可以在Pdu对象上加载、卸载Vb对象。
6、Snmptarget类
抽象目标类。在SNMP++中SnmpTarget有2个子类:CTarget(基于共同体的目标类,用于SNMPv1和SNMPv2)和UTarget(基于用户的目标类,用于SNMPv3)。每个target都与一个地址对象关联。每个target都有重发机制,超时和重发。
五、SNMP编程流程
1、调用Snmp::socket_startup;//初始化socket子系统
2、创建所需的对象,并初始化
UdpAddress address(“192.168.0.17”);//udp地址
address.set_port(161); //udp地址对象的端口号
Oid oid("1.3.6.1.2.1.1.1.0");//创建Oid对象
Pdu pdu;//创建pdu对象
Vb vb;//创建vb对象
vb.set_oid(oid);//将Oid对象绑定到Vb对象上
pdu+=vb;//将Vb对象添加到Pdu对象的末尾
Ctarget ctarget(address); //利用已创建的address对象创建CTarget对象
ctarget.set_version(version);//设置SNMP版本
ctarget.set_retry(retries);//设置重传次数
ctarget.set_timeout(timeout);//设置超时时间
ctarget.set_readcommunity(community);//设置共同体
SnmpTarget* target;//创建snmptarget对象指针
target=&ctarget;//将snmptarget对象指针指向Ctargett对象;
Snmp snmp(status);//创建一个snmp++会话
if (status=snmp.get(pdu,target)!=SNMP_CLASS_SUCCESS) //向代理站请求MIB信息,正常情况下代理进程将发送一个Getresponse报文,该返回的pdu中将包含变量名和相应值。
cout< else{ pdu.get_vb(vb,0); //取出pdu中vb绑定的 cout<<“oid=”< cout< } 六、接收Trap #include “snmp_pp.h” //-----------------[ trap callback function definition]------------------------------------------------------------------- int status; cout << “Error constructing Snmp Object\n”; else { OidCollection trapids; if ( status = snmp->notify_register( trapids, targets, & my_trap_callback)) != SNMP_CLASS_SUCCESS) cout << “ Snmp Trap Register Error “ << snmp->error_msg( status); 参考: SNMP++官方文档http://www.agentpp.com/doc_snmp++3.x/index.html 陈云昊翻译的SNMP++中文说明资料 基于SNMP_类库的简单网络管理平台的实现_周志成
void my_trap_callback (
int reason, // reason
Snmp* session, // session handle
Pdu & pdu, // trap pdu
TimeTicks ×tamp, // timestamp
SnmpTarget &target, // source of the trap
void * cbd) // optional callback data
{
Address *address;
unsigned char get_cummunity[80], set_community[80];
unsigned long timeout;
int retry;
if ( reason == SNMP_CLASS_TRAP)
{
target.resolve_to_C(
get_community, // get community
set_community, // set community
&address, // address object
timeout, // timeout
retry); // retry
cout << “Trap Received from << address->get_printable() << “Trap Id = “ << trapid.get_printable();
}
else
cout << “Trap Receive Error = “ << session->error_msg( reason);
};
//---------------[ trap receive register ]---------------------------------------------------------------------
Snmp *snmp; // dynamic Snmp object
void trap_register()
{ //----------------[ instantiate an Snmp object, delete when no longer receiving traps ]------------
snmp = new Snmp( status);
if (( snmp == NULL) || ( status != SNMP_CLASS_SUCCESS))
//-------[ set up two empty collections, empty denotes receive all ]-------------------------------
TargetCollection targets;
//------[ invoke the regsiter ]----------------------
}