概念:snmp 是专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及HUBS等)的一种标准协议,是应用层协议。

组成部分(基于TCP/IP的SNMP网络管理框架):

管理信息结构SMI(Structure ofManagement Information)、管理信息库MIB和管理协议SNMP。

SNMP中的MIB是一种树状数据库,MIB管理的对象,就是树的端节点,每个节点都有唯一位置和唯一名字.IETF规定管理信息库对象识别符(OID,Object Identifier)唯一指定,其命名规则就是父节点的名字作为子节点名字的前缀。

组成部分:

一个SNMP管理的网络由下列三个关键组件组成:

1 网络管理系统(NMS,Network-management systems)运行应用程序,以该应用程序监视并控制被管理的设备。也称为管理实体(managingentity),网络管理员在这儿与网络设备进行交互。网络管理系统提供网络管理需要的大量运算和记忆资源。一个被管理的网络可能存在一个以上的网络管理系统。

2 被管理的设备(managed device)是一个网络节点,它包含一个存在于被管理的网络中的SNMP代理者。被管理的设备通过管理信息库(MIB)收集并存储管理信息,并且让网络管理系统能够通过SNMP代理者取得这项信息。

3 代理者(agent)是一种存在于被管理的设备中的网络管理软件模块。代理者控制本地机器的管理信息,以和SNMP兼容的格式传送这项信息。

协议种类

SNMP : SNMPV1 (GET、GETNEXT、SET 和 TRAP)、 SNMPV2(GET、GETNEXT、SET 和 TRAP,GET BULK 和 INFORM) 、 SNMPV3(GET、GETNEXT、SET 和 TRAP,GET BULK 和 INFORM)。第 1 版和第 2 版没有太大差距,但 SNMPV2 是增强版本,包含了其它协议操作。与前两种相比, SNMPV3 则包含更多安全和远程配置。为了解决不同 SNMP 版本间的不兼容问题, RFC3584 中定义了三者共存策略。(SNMP 还包括一组由RMON、RMON2、MTB、MTB2、OCDS及OCDS定义的扩展协议)。

协议结构

SNMP 是一种应用程序协议,封装在UDP中。各种版本的 SNMP 信息通用格式如下所示(报文结构):

Version:SNMP 版本号。管理器和代理器必须使用相同版本的 SNMP。需要删除具有不同版本号的信息,并不对它们作进一步的处理。

Community:团体名称,用于在访问代理器之前认证管理器。

PDU(协议数据单元):SNMPv1、v2 和 v3 中的 PDU 类型和格式将在对应文件中作具体介绍。

应用

在大型网络管理中,网管(网络管理员)的痛点是如何实时了解不在身边的网络设备运行状况。若要亲自查看每一台网络设备的运行现状很不现实,所以实际网络中,利用SNMP协议自动帮助管理员收集网络运行状况方法应用最为广泛,网络管理员只要坐在自己位置就能了解全公司网络设备运行情况。网络管理员利用snmp(简单网络管理协议)很方便在SNMP Agent和NMS之间交换管理信息。SNMP主要作用是帮助企业网络管理人员更方便了解网络性能、发现并解决网络问题、规划网络未来发展。

关键概念理解:

MIB文件中的变量使用的名字取自ISO和ITU管理的对象标识符(object identifier)名字空间。它是一种分级树的结构。如图2所示,第一级有三个节点:ccitt、iso、iso-ccitt。低级的对象ID分别由相关组织分配。一个特定对象的标识符可通过由根到该对象的路径获得。一般网络设备取iso节点下的对象内容。如名字空间ip结点下一个名字为ipInReceives的MIB变量被指派数字值3,因而该变量的名字为:

iso.org.dod.internet.mgmt.mib.ip.ipInReceives

相应的数字表示(对象标识符OID,唯一标识一个MIB对象)为:1.3.6.1.2.1.4.3,如下图所示:

当网络管理协议在报文中使用MIB变量时,每个变量名后还要加一个后缀,以作为该变量的一个实例。如ipInReceives的实例数字表示为:1.3.6.1.2.1.4.3.0.

snmp怎么测试(SNMP及SNMP4J基本知识)(1)

mib 树结构

SMI定义了SNMP框架所用信息的组织、组成和标识,它还为描述MIB对象和描述协议怎样交换信息奠定了基础。

SMI定义的数据类型:


snmp怎么测试(SNMP及SNMP4J基本知识)(2)

各种类型

◆ 简单类型(simple)

Integer:整型是-2,147,483,648~2,147,483,647的有符号整数

octet string: 字符串是0~65535个字节的有序序列

OBJECT IDENTIFIER: 来自按照ASN.1规则分配的对象标识符集

◆ 简单结构类型(simple-constructed)

SEQUENCE 用于列表。这一数据类型与大多数程序设计语言中的“structure”类似。一个SEQUENCE包括0个或更多元素,每一个元素又是另一个ASN.1数据类型

SEQUENCE OF type 用于表格。这一数据类型与大多数程序设计语言中的“array”类似。一个表格包括0个或更多元素,每一个元素又是另一个ASN.1数据类型。

◆ 应用类型(application-wide)

IpAddress: 以网络序表示的IP地址。因为它是一个32位的值,所以定义为4个字节;

counter:计数器是一个非负的整数,它递增至最大值,而后回零。在SNMPv1中定义的计数器是32位的,即最大值为4,294,967,295;

Gauge :也是一个非负整数,它可以递增或递减,但达到最大值时保持在最大值,最大值为232-1;

time ticks:是一个时间单位,表示以0.01秒为单位计算的时间;

pdu

5种协议数据单元PDU(也就是SNMP报文),用来在管理进程和代理之间的交换。

get-request操作:从代理进程处提取一个或多个参数值。

get-next-request操作:从代理进程处提取紧跟当前参数值的下一个参数值。

set-request操作:设置代理进程的一个或多个参数值。

get-response操作:返回的一个或多个参数值。这个操作是由代理进程发出,它是前面三种操作的响应操作。trap操作:代理进程主动发出的报文,通知管理进程有某些事情发生。
前面的3种操作是由管理进程向代理进程发出的,后面的2个操作是代理进程发给管理进程的,为了简化起见,前面3个操作今后叫做get、get-next和set操作。描述了SNMP的这5种报文操作,在代理进程端是用熟知端口161俩接收get或set报文,而在管理进程端是用熟知端口162来接收trap报文。

snmp怎么测试(SNMP及SNMP4J基本知识)(3)

snmp通信


snmp怎么测试(SNMP及SNMP4J基本知识)(4)

snmp 报文结构

A 公共SNMP首部:版本 写入版本字段的是版本号减1,对于SNMP(即SNMPV1)则应写入0;
共同体(community)共同体就是一个字符串,作为管理进程和代理进程之间的明文口令,常用的是6个字符“public”。 PDU类型 根据PDU的类型,填入0~4中的一个数字:0 --get-request ,

1 --------get-next-request,2---------get-response,3----------set-request,4---------trap

B get/set首部
a 请求标识符(request ID) 这是由管理进程设置的一个整数值。代理进程在发送get-response报文时也要返回此请求标识符。管理进程可同时向许多代理发出get报文,这些报文都使用UDP传送,先发送的有可能后到达。设置了请求标识符可使管理进程能够识别返回的响应报文对于哪一个请求报文
b 差错状态(error status) 由代理进程回答时填入0~5中的一个数字,0 ---noError -----一切正常

1-----tooBig----代理无法将回答装入到一个SNMP报文之中

2----noSuchName-----操作指明了一个不存在的变量

3-----badValue---一个set操作指明了一个无效值或无效语法

4---readOnly---管理进程试图修改一个只读变量

5---genErr----某些其他的差错

c差错索引(error index) 当出现noSuchName、badValue或readOnly的差错时,由代理进程在回答时设置的一个整数,它指明有差错的变量在变量列表中的偏移。

C trap首部
企业(enterprise) 填入trap报文的网络设备的对象标识符。此对象标识符肯定是在图3的对象命名树上的enterprise结点{1.3.6.1.4.1}下面的一棵子树上。
trap类型 此字段正式的名称是generic-trap,7种。

trap类型 名字 说明

0-----coldStart----代理进行了初始化

1----warmStart---代理进行了重新初始化

2---linkDown---一个接口从工作状态变为故障状态

3----linkUp----一个接口从故障状态变为工作状态

4----authenticationFailure-----从SNMP管理进程接收到具有一个无效共同体的报文

5----egpNeighborLoss----一个EGP相邻路由器变为故障状态

6---enterpriseSpecific----代理自定义的事件,需要用后面的“特定代码”来指明

当使用上述类型2、3、5时,在报文后面变量部分的第一个变量应标识响应的接口。
特定代码(specific-code) 指明代理自定义的时间(若trap类型为6),否则为0。

时间戳(timestamp) 指明自代理进程初始化到trap报告的事件发生所经历的时间,单位为10ms。例如时间戳为1908表明在代理初始化后1908ms发生了该时间。
D变量绑定(variable-bindings)
指明一个或多个变量的名和对应的值。在get或get-next报文中,变量的值应忽略(了解一下:管理变量的表示方法是这样规定的:形如x.y,其中x是管理对象的object identifer。y是能唯一确定对象类型值的一组数字,在非表型变量中为0,在表型变量中是这个表的索引,比如接口表中的接口号,或路由表中的目的网络地址等等 。如:在MIB文件里定义了ipAdEntNetMask这一管理对象,其object identifier为1.3.6.1.1.5.6.1.3它是个路由表中的一项,它的一个实例就是路由表中某一行的子网掩码,如果这行的索引、目的网络地址为129.102.1.0。则这个变量名是:1.3.6.1.1.5.6.1.3.129.102.1.0。在以后的说明中,为了方便,把唯一确定管理变量的一组数字,也就是x.y中的y称作实例。)

举个例子:

SNMPv1原始报文内容:

00 23 5a 9e 58 b9 00 4c 41 49 50 55 08 00 45 00 00 48 00 00 40 00 40 11 a5 4e c0 a8 0a 01 c0 a8 0a 05 0c 00 00 a2 00 34 ff e0 30 2a 02 01 00 04 06 70 75 62 6c 69 63 a4 1d 06 0a 2b 06 01 04 01 bf 08 03 02 0a 40 04 c0 a8 0a 01 02 01 00 02 01 00 43 01 0e 30 00

目的MAC:00 23 5a 9e 58 b9 源MAC:00 4c 41 49 50 55 协议类型:08 00 ,为IP数据报 IP头:45 00 00 48 00 00 40 00 40 11 a5 4e c0 a8 0a 01 c0 a8 0a 05 0c UDP头:0c 00 00 a2 00 34 ff e0

其余部分都为SNMP报文: 30 表示SNMP消息是ASN.1的SEQUENCE类型; 2a 表示该SNMP报文的总长度是42(0x2a)个字节,该字段所表示的报文长度起始于它后面的第一个字节直到报文结束; 02 01 00 表示版本号,可见其确实为BER编码方式。02表示该字段是INTEGER类型;01表示该字段占1个字节;00表示版本号,该值为“版本号-1”; 04 06 70 75 62 6c 69 63 表示团体名,04表示该字段为OCTET STRING类型;06表示该字段占6个字节;70 75 62 6c 69 63 表示团体名的ANSII码的十六进制形式,这里是“public”; a4 1d 其中a4中的“4”表示这是一个trap报文,a4又叫报文的标签标记;1d表示后面还有29(0x1d)个字节的数据; 06 0a 2b 06 01 04 01 bf 08 03 02 0a 企业OID标识。06表示该字段是个对象标识符,OBJECT IDENTIFIER;0a表示该字段占10(0x0a)个字节;关于SNMP的OID的编码方式有些奇特:例如1.3.6.1.2…. 取前两个数字分别记为x和y。编码时40*x y,这里x=1,y=3,因此结果为40*1 3=43,即表示十六进制的2b。因此,这里的企业OID编码即为1.3.6.1.4.1.8072.3.2.10; 40 04 c0 a8 0a 01 同样40表示该字段为OCTET STRING 类型;04表示IP地址占4个字节;IP地址为192.168.10.1; 02 01 00 其中00表示trap类型为coldStart; 02 01 00 其中00表示我们指定的trap即specific-trap也为coldStart类型; 43 01 0e 43表示为TimeTicks类型;01表示该字段占1个字节;0e即十进制的14表示时间标签为0.14秒,这里时间计数器以0.01秒递增;30 00 30表示“键-值”值对的编码类型为SEQUENCE;00表示该字段占0个字节,即没有该字段。

snmp怎么测试(SNMP及SNMP4J基本知识)(5)

snmpv2 trap的报文格式

SNMPv2原始报文内容:

00 23 5a 9e 58 b9 00 4c 41 49 50 55 08 00 45 00 00 7b 00 00 40 00 40 11 a5 1b c0 a8 0a 01 c0 a8 0a 05 0c 01 00 a2 00 67 04 bb 30 5d02 01 01 04 06 70 75 62 6c 69 63 a7 50 02 04 17 73 2c fb 02 01 00 02 01 00 30 42 30 0d 06 08 2b 06 01 02 01 01 03 00 43 01 0e 30 1706 0a 2b 06 01 06 03 01 01 04 01 00 06 09 2b 06 01 06 03 01 01 05 01 30 18 06 0a 2b 06 01 06 03 01 01 04 03 00 06 0a 2b 06 01 04 01 bf 08 03 02 0a

目的MAC:00 23 5a 9e 58 b9 源MAC:00 4c 41 49 50 55

协议类型:08 00,IP报文 IP头:45 00 00 7b 00 00 40 00 40 11 a5 1b c0 a8 0a 01 c0 a8 0a 05

UDP头:0c 01 00 a2 00 67 04 bb 余下部分全为SNMP报文内容,约定:

xx 标注类型;xx 标注长度;xx 标注真正的数据。

30 5d 整个SNMP报文的编码方式为30,即SEQUENCE类型,报文长度93(0x5d)字节; 02 01 01 版本号01即v2版本; 04 06 70 75 62 6c 69 63 团体名70 75 62 6c 69 63 即英文的“public”; a7 50 a7表示trap类型为7,即厂商自定义trap;50表示PDU区段占80(0x50)字节; 02 04 17 73 2c fb 请求ID为17 73 2c fb 十进制的393424123; 02 01 00 错误状态0;02 01 00 错误索引0;30 42 “变量名-值”对编码类型30 即SEQUENCE类型;“变量名-值”所占总字节0x42,即66字节;30 0d 06 08 2b 06 01 02 01 01 03 00 43 01 0e 第一个“名-值”对区段编码方式30 即SEQUENCE类型;第一个“名-值”对总长度0x0d,13字节;第一个变量名的编码类型0x06,时间标签;第一个变量名占0x08个字节;第一个变量名2b 06 01 02 01 01 03 00,为1.3.6.1.2.1.1.3.0;第一个变量值为0x0e,即14;30 17 06 0a 2b 06 01 06 03 01 01 04 01 00 06 09 2b 06 01 06 03 01 01 05 01 第二个“名-值”对;变量名1.3.6.1.6.3.1.1.4.1.0;变量值1.3.6.1.6.3.1.1.5.1;30 18 06 0a 2b 06 01 06 03 01 01 04 03 00 06 0a 2b 06 01 04 01 bf 08 03 02 0a 第三个“名-值”对;变量名1.3.6.1.6.3.1.1.4.3.0;变量值1.3.6.1.4.1.8072.3.2.10;

本文的重点:

SNMP4J是一个用Java来实现SNMP(简单网络管理协议)协议的开源项目.它支持以命令行的形式进行管理与响应。

基本知识:

Snmp类:该类是SNMP4J中最为核心的类。负责SNMP报文的接受和发送。它提供了发送和接收PDU的方法,所有的PDU类型都可以采用同步或者异步的方式被发送。

SNMP报文单元的抽象,其中PDU类适用于SNMPv1和SNMPv2c。ScopedPDU类继承于PDU类,适用于SNMPv3。

对应于SNMP代理的地址信息,包括IP地址和端口号(161)。其中Target接口适用于SNMPv1和SNMPv2c。CommunityTarget类实现了Target接口,用于SNMPv1和SNMPv2c这两个版本,UserTarget类实现了Target接口,适用于SNMPv3。

TransportMapping接口 该接口代表了SNMP4J所使用的传输层协议。这也是SNMP4J一大特色的地方。按照RFC的规定,SNMP是只使用UDP作为传输层协议的。而SNMP4J支持管理端和代理端使用UDP或者TCP进行传输。该接口有两个子接口

  Target代表远程设备或者远程实体、PDU代表管理端同Target通信的数据,Snmp就代表管理者管理功能(其实就是数据的收发)的具体执行者。

  打个比方:Target就是你远方的恋人,PDU就是你们之间传递的情书、而Snmp就是负责帮你寄信收信的邮差。

SNMP4J支持两种消息发送模式:同步发送模式和异步发送模式。

同步发送模式也称阻塞模式。当管理端发送出一条消息之后,线程会被阻塞,直到收到对方的回应或者时间超时。同步发送模式编程较为简单,但是不适用于发送广播消息。

异步发送模式也称非阻塞模式。当程序发送一条消息之后,线程将会继续执行,当收到消息的回应的时候,程序会对消息作出相应的处理。要实现异步发送模式,需要实例化一个实现了ResponseListener接口的类的对象。ResponseListener接口中有一个名为onResponse的函数。这是一个回调函数,当程序收到响应的时候,会自动调用该函数。由该函数完成对响应的处理。

使用SNMP4J实现管理端的步骤 利用SNMP4J编写SNMP管理端:

1 、初始化

①、明确SNMP在传输层所使用的协议,使用UDP协议作为SNMP的传输层协议,所以我们需要实例化的是一个DefaultUdpTransportMapping接口对象;

②、实例化一个snmp对象 将1中实例化的DefaultUdpTransportMapping接口的对象作为参数传到snmp类的构造函数中。如果实现的SNMPv3协议,我们还需要设置安全机制,添加安全用户等等;

③、监听snmp消息 调用刚刚实例化的DefaultUdpTransportMapping的接口对象的listen方法,让程序监听snmp消息;

2、 构造发送目标

  若实现的是SNMPv2c或者说SNMPv1,需要实例化一个CommunityTarget对象。实现的是SNMPv3程序,则需要实例化一个UserTarget对象。

  之后,需要对实例化的对象做一些设置。如果是CommunityTarget的对象,则需要设置使用的Snmp版本,重传时间和等待时延。如果是UserTarget对象,我们不仅需要设置版本、重传时间、等待时延,还需要设置安全级别和安全名称。

3、 构造发送报文

  如果发送的是SNMPv2c或者说SNMPv1的报文,需要实例化一个PDU类的对象。如果发送的是SNMPv3的报文,则需要实例化一个ScopedPDU类的对象。之后,还需要生成一个OID对象,其中包含了我们所需要获取的SNMP对象在MIB库中的ID。然后我们需要将OID和之前生成的PDU对象或者是ScopedPDU对象绑定,并且设置PDU的报文类型(五种SNMP报文类型之一)。

4、 构造响应监听对象(异步模式)

  当使用异步模式的时候,我们需要实例化一个实现了ResponseListener接口的对象,作为响应消息的监听对象。在构造该对象的过程中,我们需要重写ResponseListener的OnResponse函数,该函数是一个回调函数,用来处理程序收到响应后的一些操作。

5、 发送消息

  上述操作都设置完毕可以发送消息。同步模式和异步模式发送消息调用的函数名字均为send,但是两个函数所需参数不一样。同步模式的参数仅为2和3中构造的目标对象和报文对象,而异步模式还需要4中构造的监听对象。

  同步模式发送消息后便等待响应的到达,到达之后会返回一个ResponseEvent对象,该对象中包含了响应的相应信息。

  异步模式发送消息之后便会继续执行,当收到响应消息时便会调用监听对象的OnResponse函数。该函数中的语句便是我们对响应的处理

使用SNMP4J实现管理端的编程实现

  ①、设定远程实体 snmp4j中,用CommunityTarget对象来表示远程实体(要进行snmp消息通信的远程主机,使用snmp的v2版本)

  ②、指定远程实体的地址 snmp4j中使用Address接口对象来表示,Address对象需要通过实现该接口的类的对象向上转型来实例化

  ③、通过CommunityTarget以及其父接口中提供的setXX方法来设定远程实体的属性,如设定远程实体的snmp共同体属性、远程实体的地址、超时时间、重传次数、snmp版本等

  ④、设定使用的传输协议 snmp4j中,用TransportMapping接口的对象来表示传输协议(tcp/udp)

  ⑤、调用TransportMapping中的listen()方法,启动监听进程,接收消息,由于该监听进程是守护进程,最后应调用close()方法来释放该进程

  ⑥、创建SNMP对象,用于发送请求PDU

  a、创建请求pdu,即创建PDU类的对象,调用PDU类中的add()方法绑定要查询的OID,调用PDU中的setType()方法来确定该pdu的类型(与snmp中五种操作想对应)

  b、通过PDU的构造方法 public SNMP(TransportMapping transportingMapping),或者其他构造方法来生成pdu,之后调用 ResopnseEvent send(PDU pdu,Target target)发送pdu,该方法返回一个ResponseEvent对象

  ⑦、通过ResponseEvent对象来获得SNMP请求的应答pdu,方法:public PDU getResponse()

  ⑧、通过应答pdu获得mib信息(之前绑定的OID的值),方法:VaribleBinding get(int index)

上述了解下:具体看代码:

// 获取远程计算机名称

public class Snmp4jDemo {

private Snmp snmp = null;

private int version ;

public Snmp4jDemo(int version) {

try {

this.version = version;

TransportMapping transport = new DefaultUdpTransportMapping();

snmp = new Snmp(transport);

if (version == SnmpConstants.version3) {

// 设置安全模式

USM usm = new USM(SecurityProtocols.getInstance(),new OctetString(MPv3.createLocalEngineID()), 0);

SecurityModels.getInstance().addSecurityModel(usm);

}

// 开始监听消息

transport.listen();

} catch (IOException e) {

e.printStackTrace();

}

}

public void sendMessage(Boolean syn, final Boolean bro, PDU pdu, String addr)

throws IOException {

// 生成目标地址对象

Address targetAddress = GenericAddress.parse(addr);

Target target = null;

if (version == SnmpConstants.version3) {

// 添加用户

snmp.getUSM().addUser(new OctetString("MD5DES"),new UsmUser(new OctetString("MD5DES"), AuthMD5.ID,new OctetString("MD5DESUserAuthPassword"),PrivDES.ID, new OctetString("MD5DESUserPrivPassword")));

target = new UserTarget();

// 设置安全级别

((UserTarget) target).setSecurityLevel(SecurityLevel.AUTH_PRIV);

((UserTarget) target).setSecurityName(new OctetString("MD5DES"));

target.setVersion(SnmpConstants.version3);

} else {

target = new CommunityTarget();

if (version == SnmpConstants.version1) {

target.setVersion(SnmpConstants.version1);

((CommunityTarget) target).setCommunity(new OctetString("public"));

} else {

target.setVersion(SnmpConstants.version2c);

((CommunityTarget) target).setCommunity(new OctetString("public"));

}

}

// 目标对象相关设置

target.setAddress(targetAddress);

target.setRetries(5);

target.setTimeout(1000);

if (!syn) {

// 发送报文 并且接受响应

ResponseEvent response = snmp.send(pdu, target);

// 处理响应

System.out.println("Synchronize(同步) message(消息) from(来自) "

response.getPeerAddress() "\r\n" "request(发送的请求):"

response.getRequest() "\r\n" "response(返回的响应):"

response.getResponse());

/**

* 输出结果:

* Synchronize(同步) message(消息) from(来自) 192.168.1.233/161

request(发送的请求):GET[requestID=632977521, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1.5.0 = Null]]

response(返回的响应):RESPONSE[requestID=632977521, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.2.1.1.5.0 = WIN-667H6TS3U37]]

*/

} else {

// 设置监听对象

ResponseListener listener = new ResponseListener() {

public void onResponse(ResponseEvent event) {

if (bro.equals(false)) {

((Snmp) event.getSource()).cancel(event.getRequest(),this);

}

// 处理响应

PDU request = event.getRequest();

PDU response = event.getResponse();

System.out.println("Asynchronise(异步) message(消息) from(来自) "

event.getPeerAddress() "\r\n" "request(发送的请求):" request

"\r\n" "response(返回的响应):" response);

}

};

// 发送报文

snmp.send(pdu, target, null, listener);

}

}

public static void main(String[] args) {

//Snmp的三个版本号

//int ver3 = SnmpConstants.version3;

int ver2c = SnmpConstants.version2c;

//int ver1 = SnmpConstants.version1;

Snmp4jDemo manager = new Snmp4jDemo(ver2c);

// 构造报文

PDU pdu = new PDU();

//PDU pdu = new ScopedPDU();

// 设置要获取的对象ID,这个OID代表远程计算机的名称

OID oids = new OID("1.3.6.1.2.1.1.5.0");

pdu.add(new VariableBinding(oids));

// 设置报文类型

pdu.setType(PDU.GET);

//((ScopedPDU) pdu).setContextName(new OctetString("priv"));

try {

// 发送消息 其中最后一个是想要发送的目标地址

//manager.sendMessage(false, true, pdu, "udp:192.168.1.229/161");//192.168.1.229 Linux服务器

manager.sendMessage(false, true, pdu, "udp:192.168.1.233/161");//192.168.1.233 WinServer2008服务器

} catch (IOException e) {

e.printStackTrace();

}

}

}

// 获取本机消息

public class GetOID {

public static void main(String[] args) throws Exception{

try{

//设定CommunityTarget

CommunityTarget myTarget = new CommunityTarget();

//定义远程主机的地址

//Address deviceAdd = GenericAddress.parse("udp:192.168.1.233/161");

//定义本机的地址

Address localAdd = GenericAddress.parse("udp:localhost/161");

//设定远程主机的地址

//myTarget.setAddress(deviceAdd);

//设定本地主机的地址

myTarget.setAddress(localAdd);

//设置snmp共同体

myTarget.setCommunity(new OctetString("public"));

//设置超时重试次数

myTarget.setRetries(2);

//设置超时的时间

myTarget.setTimeout(5*60);

//设置使用的snmp版本

myTarget.setVersion(SnmpConstants.version2c);

//设定采取的协议

TransportMapping transport = new DefaultUdpTransportMapping();//设定传输协议为UDP

//调用TransportMapping中的listen()方法,启动监听进程,接收消息,由于该监听进程是守护进程,最后应调用close()方法来释放该进程

transport.listen();

//创建SNMP对象,用于发送请求PDU

Snmp protocol = new Snmp(transport);

//创建请求pdu,获取mib

PDU request = new PDU();

//调用的add方法绑定要查询的OID

request.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1")));

request.add(new VariableBinding(new OID(new int[] {1,3,6,1,2,1,1,2})));

//调用setType()方法来确定该pdu的类型

request.setType(PDU.GETNEXT);

//调用 send(PDU pdu,Target target)发送pdu,返回一个ResponseEvent对象

ResponseEvent responseEvent = protocol.send(request, myTarget);

//通过ResponseEvent对象来获得SNMP请求的应答pdu,方法:public PDU getResponse()

PDU response=responseEvent.getResponse();

//输出

if(response != null){

System.out.println("request.size()=" request.size());

System.out.println("response.size()=" response.size());

//通过应答pdu获得mib信息(之前绑定的OID的值),方法:VaribleBinding get(int index)

VariableBinding vb1 = response.get(0);

VariableBinding vb2 = response.get(1);

System.out.println(vb1);

System.out.println(vb2);

//调用close()方法释放该进程

transport.close();

/**

* 输出结果:

* request.size()=2

response.size()=2

1.3.6.1.2.1.1.1.0 = Hardware: x86 Family 6 Model 58 Stepping 9 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Multiprocessor Free)

1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.311.1.1.3.1.1

*/

}

}catch(IOException e){

e.printStackTrace();

}

}

}



发送trap:

public class SnmpSendTrap {

private Snmp snmp = null;

private Address targetAddress = null;

public void initComm() throws IOException {

// 设置管理进程的IP和端口

targetAddress = GenericAddress.parse("udp:192.168.1.23/162");

TransportMapping transport = new DefaultUdpTransportMapping();

snmp = new Snmp(transport);

transport.listen();

}

/**

* 向管理进程发送Trap报文

*/

public void sendPDU() throws IOException {

// 设置 target

CommunityTarget target = new CommunityTarget();

target.setAddress(targetAddress);

// 通信不成功时的重试次数

target.setRetries(2);

// 超时时间

target.setTimeout(1500);

// snmp版本

target.setVersion(SnmpConstants.version2c);

// 创建 PDU

PDU pdu = new PDU();

pdu.add(new VariableBinding(new OID(".1.3.6.1.2.3377.10.1.1.1.1"),

new OctetString("SnmpTrap")));

pdu.add(new VariableBinding(new OID(".1.3.6.1.2.3377.10.1.1.1.2"),

new OctetString("hello world")));

pdu.setType(PDU.TRAP);

// 向Agent发送PDU,并接收Response

ResponseEvent respEvnt = snmp.send(pdu, target);

// 解析Response

if (respEvnt != null && respEvnt.getResponse() != null) {

Vector<VariableBinding> recVBs = respEvnt.getResponse()

.getVariableBindings();

for (int i = 0; i < recVBs.size(); i ) {

VariableBinding recVB = recVBs.elementAt(i);

System.out.println(recVB.getOid() " : " recVB.getVariable());

}

}

}

public static void main(String[] args) {

try {

SnmpSendTrap util = new SnmpSendTrap();

util.initComm();

util.sendPDU();

} catch (IOException e) {

e.printStackTrace();

}

}

}

1、运行MultiThreadedTrapReceiver类,提示“开始监听Trap信息!”并处理监听状态

2、运行SnmpSendTrap类,运行完毕后,将会在“开始监听Trap信息!”后面显示:

1.3.6.1.2.3377.10.1.1.1.1 : SnmpTrap

1.3.6.1.2.3377.10.1.1.1.2 : helloworld


snmp怎么测试(SNMP及SNMP4J基本知识)(6)

世界你好

,