`
cuisuqiang
  • 浏览: 3962337 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
3feb66c0-2fb6-35ff-968a-5f5ec10ada43
Java研发技术指南
浏览量:3671778
社区版块
存档分类
最新评论

SNMP 使用SNMP4J V2进行同步和异步 GET,SET

阅读更多

重要的类和接口
Snmp类:该类是SNMP4J中最为核心的类。负责SNMP报文的接受和发送。
PDU类和ScopedPDU类:该类是SNMP报文单元的抽象,其中PDU类适用于SNMPv1和SNMPv2c。ScopedPDU类继承于PDU类,适用于SNMPv3。
Target接口和UserTarget类:对应于SNMP代理的地址信息,包括IP地址和端口号(161)。其中Target接口适用于SNMPv1和SNMPv2c。UserTarget类实现了Target接口,适用于SNMPv3。
TransportMapping接口:该接口代表了SNMP4J所使用的传输层协议。这也是SNMP4J一大特色的地方。按照RFC的规定,SNMP是只使用UDP作为传输层协议的。而SNMP4J支持管理端和代理端使用UDP或者TCP进行传输。该接口有两个子接口。

两种消息发送模式
SNMP4J支持两种消息发送模式:同步发送模式和异步发送模式。
其中同步发送模式也称阻塞模式。当管理端发送出一条消息之后,线程会被阻塞,直到收到对方的回应或者时间超时。同步发送模式编程较为简单,但是不适用于发送广播消息。
异步发送模式也称非阻塞模式。当程序发送一条消息之后,线程将会继续执行,当收到消息的回应的时候,程序会对消息作出相应的处理。要实现异步发送模式,需要实例化一个实现了ResponseListener接口的类的对象。ResponseListener接口中有一个名为onResponse的函数。这是一个回调函数,当程序收到响应的时候,会自动调用该函数。由该函数完成对响应的处理。

实现管理端的总体步骤
该部分说明了利用SNMP4J编写SNMP管理端的大致过程,读者在阅读之后会对SNMP4J有一个宏观上的认识。在附录部分,作者给出了一个用SNMP4J开发管理站的样例程序,如果有进一步的需要,请参考附录部分。
初始化
明确SNMP在传输层所使用的协议
一般情况下,我们都使用使用UDP协议作为SNMP的传输层协议,所以我们需要实例化的是一个DefaultUdpTransportMapping接口对象;
实例化一个snmp对象
在此过程中,我们需要将1中实例化的DefaultUdpTransportMapping接口的对象作为参数,穿snmp类的构造函数中。
另外,如果实现的SNMPv3协议,我们还需要设置安全机制,添加安全用户等等;
监听snmp消息
在此,我们可以调用刚刚实例化的DefaultUdpTransportMapping的接口对象的listen方法,让程序监听snmp消息;
构造发送目标
如果实现的是SNMPv3程序,则需要实例化一个UserTarget对象,如果实现的是SNMPv2c或者说SNMPv1,则需要实例化一个CommunityTarget对象。
之后,我们还需要对实例化的对象做一些设置。如果是CommunityTarget的对象,则需要设置版本,重传时间和等待时延。如果是UserTarget对象,我们不仅需要设置版本、重传时间、等待时延,还需要设置安全级别和安全名称。
构造发送报文
如果发送的是SNMPv3的报文,我们则需要实例化一个ScopedPDU    类的对象,否则我们需要实例化一个PDU类的对象。之后,我们还需要生成一个OID对象,其中包含了我们所需要获取的SNMP对象在MIB库中的ID。然后我们需要将OID和之前生成的PDU对象或者是ScopedPDU对象绑定,并且设置PDU的报文类型(五种SNMP报文类型之一)。
构造响应监听对象(异步模式)
当使用异步模式的时候,我们需要实例化一个实现了ResponseListener
的对象,作为响应消息的监听对象。在构造该对象的过程中,我们需要重写ResponseListener的OnResponse函数,该函数是一个回调函数,用来处理程序收到响应后的一些操作。
发送消息
当所有上述操作都设置完毕之后,就可以发送消息了。同步模式和异步模式发送消息调用的函数名字均为send,但是两个函数所需参数不一样。同步模式的参数仅为4.3.2和4.3.3中构造的目标对象和报文对象,而异步模式还需要4.3.4中构造的监听对象。
同步模式发送消息后便等待响应的到达,到达之后会返回一个ResponseEvent对象,该对象中包含了响应的相应信息。
异步模式发送消息之后便会继续执行,当收到响应消息时便会调用监听对象的OnResponse函数。该函数中的语句便是我们对响应的处理!

 

我们来进行一个同步的GET操作,假如你已经有了可以访问的端口:

package t1;

import java.io.IOException;
import java.util.Vector;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

/**
 * @说明 SNMP4J测试
 * @author cuisuqiang
 * @version 1.0
 * @since
 */
public class SnmpUtil {
	private Snmp snmp = null;
	private Address targetAddress = null;

	public void initComm() throws IOException {
		// 设置Agent方的IP和端口
		targetAddress = GenericAddress.parse("udp:192.168.0.148/22500");
		TransportMapping transport = new DefaultUdpTransportMapping();
		snmp = new Snmp(transport);
		transport.listen();
	}

	public ResponseEvent sendPDU(PDU pdu) throws IOException {
		// 设置 目标
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString("public"));
		target.setAddress(targetAddress);
		// 通信不成功时的重试次数 N+1次
		target.setRetries(2);
		// 超时时间
		target.setTimeout(2 * 1000);
		// SNMP 版本
		target.setVersion(SnmpConstants.version2c);
		// 向Agent发送PDU,并返回Response
		return snmp.send(pdu, target);
	}

	public void getPDU() throws IOException {
		// PDU 对象
		PDU pdu = new PDU();
		pdu.add(new VariableBinding(new OID("1.2.3.4.5.6")));
		// 操作类型
		pdu.setType(PDU.GET);
		ResponseEvent revent = sendPDU(pdu);
		if(null != revent){
			readResponse(revent);
		}
	}

	@SuppressWarnings("unchecked")
	public void readResponse(ResponseEvent respEvnt) {
		// 解析Response
		System.out.println("------------>解析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().toString());
			}
		}
	}

	public static void main(String[] args) {
		try {
			SnmpUtil util = new SnmpUtil();
			util.initComm();
			util.getPDU();
		} catch (IOException e) {
			e.printStackTrace();

		}
	}
}

 

我的被管设备返回了:

------------>解析Response<-------------
0.0 : xxx
1.3.6.1.2.1.1.6.0 : 12345
1.3.6.1.2.1.1.2.0 : 54321

 

这个GET操作我们只发送了一个OID过去,但是你不能确定会收到多少OID的数据,因为这是双方约定的而不是协议定死的!

消息发送后会产生等待,如果超时时间内没有响应则直接过去!

 

那么异步是怎样实现的呢?其实很简单,只需对上面代码简单修改:

package t1;

import java.io.IOException;
import java.util.Vector;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

/**
 * @说明 SNMP4J测试
 * @author cuisuqiang
 * @version 1.0
 * @since
 */
public class SnmpUtil {
	private Snmp snmp = null;
	private Address targetAddress = null;

	public void initComm() throws IOException {
		// 设置Agent方的IP和端口
		targetAddress = GenericAddress.parse("udp:192.168.0.148/22500");
		TransportMapping transport = new DefaultUdpTransportMapping();
		snmp = new Snmp(transport);
		transport.listen();
	}

	public ResponseEvent sendPDU(PDU pdu) throws IOException {
		// 设置 目标
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString("public"));
		target.setAddress(targetAddress);
		// 通信不成功时的重试次数 N+1次
		target.setRetries(2);
		// 超时时间
		target.setTimeout(2 * 1000);
		// SNMP 版本
		target.setVersion(SnmpConstants.version2c);

		// 设置监听对象
		ResponseListener listener = new ResponseListener() {
			public void onResponse(ResponseEvent event) {
				System.out.println("---------->开始异步解析<------------");
				readResponse(event);
			}
		};
		// 发送报文
		snmp.send(pdu, target, null, listener);
		return null;
	}

	public void getPDU() throws IOException {
		// PDU 对象
		PDU pdu = new PDU();
		pdu.add(new VariableBinding(new OID("1.2.3.4.5.6")));
		// 操作类型
		pdu.setType(PDU.GET);
		ResponseEvent revent = sendPDU(pdu);
		if(null != revent){
			readResponse(revent);
		}
	}

	@SuppressWarnings("unchecked")
	public void readResponse(ResponseEvent respEvnt) {
		// 解析Response
		System.out.println("------------>解析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().toString());
			}
		}
	}

	public static void main(String[] args) {
		try {
			SnmpUtil util = new SnmpUtil();
			util.initComm();
			util.getPDU();
		} catch (IOException e) {
			e.printStackTrace();

		}
	}
}

 

被管设备返回的内容是一样的,但是我们的控制台打印不太一样:

---------->开始异步解析<------------
------------>解析Response<-------------
0.0 : xxx
1.3.6.1.2.1.1.6.0 : 12345
1.3.6.1.2.1.1.2.0 : 54321

 

因为我们采用了异步模式!

 

那么如何SET呢?

我们只需要把操作类型改为SET,然后在UDP中设置参数即可:

pdu.add(new VariableBinding(new OID("1.2.3.4.5.6"),new OctetString("priv")));
// 操作类型
pdu.setType(PDU.SET);

 

这里我们传递了一个字符串!打开SNMP4J源码或API,我们看到:

  /**
   * Creates an octet string from a java string.
   *
   * @param stringValue
   *    a Java string.
   */
  public OctetString(String stringValue) {
    this.value = stringValue.getBytes();
  }

 

然后我们在源码中还能看到这样的构造函数:

  /**
   * Creates an octet string from an byte array.
   * @param rawValue
   *    an array of bytes.
   */
  public OctetString(byte[] rawValue) {
    this(rawValue, 0, rawValue.length);
  }

 

其实很简单,因为SNMP4J本身发送的就是一组字节流,你设置的字符串其实在构造中还是获得了这个字符串的字节流信息,其实你完全可以设置一个字节流进去!

 

所以,对于OID的参数,简单来说就是一组BYTE!

 

请您到ITEYE看我的原创:http://cuisuqiang.iteye.com

或支持我的个人博客,地址:http://www.javacui.com

 

3
0
分享到:
评论
2 楼 di1984HIT 2018-03-04  
!!!!!!
1 楼 pangchaofu 2013-09-05  
不错,很详细,学习了

相关推荐

    C# snmp get和set方法实现,含源码

    在C#中实现SNMP操作,主要包括GET和SET请求,这两个是SNMP协议的基础操作。 GET方法在SNMP中用于查询网络设备的状态或获取特定变量的值。GET请求通常由管理站(如你的C#应用程序)发起,然后由代理(网络设备)响应...

    snmpv1.zip_SNMP_SNMP set_snmp get_snmp java_snmp++

    在SNMP v1中,主要有三种操作类型:GET、SET和TRAP。GET操作用于从网络设备(被称为代理,Agent)获取管理信息,SET操作则用来设置设备的配置参数,而TRAP则是设备主动发送给管理站(Manager)的报警或通知信息。 1...

    snmp4j.rar_SNMP4J-API_java 软件_snmp4j_snmp4j开发_网络管理软件

    SNMP4J是基于这个协议的Java实现,它遵循SNMP v1、v2c和v3规范,提供了丰富的类库,支持各种SNMP操作,如Get、Set、Trap等。 **SNMP4J的主要特性:** 1. 全面支持SNMP v1、v2c和v3:SNMP4J不仅支持基础的v1和v2c...

    snmp4j-1.9.3d.zip

    2. **异步和同步API**:SNMP4J提供了同步和异步两种方式发送SNMP请求,异步模式对于处理大量并发请求非常有用,可以提高系统性能。 3. **易于使用**:SNMP4J的API设计简洁,易于理解和使用。通过简单的代码即可构建...

    snmp4j-2.3.0源码等

    SNMP4J使用MIB-2库来处理MIB对象,包括OID(Object Identifier)的解析和处理。 6. **Event Handling**: SNMP4J提供了一个事件模型,可以注册监听器来处理SNMP响应和陷阱事件。 7. **Target Objects**: 为了...

    snmp4j文档 提供了对snmp的封装

    SNMP4J提供了对SNMPv1、SNMPv2c和SNMPv3的支持,涵盖了各种安全模型和认证机制。 在SNMP4J中,有几个关键的接口和类,它们构成了SNMP通信的基础: 1. `Session`接口:这是SNMP通信的核心,它定义了与SNMP代理进行...

    SNMP4j学习开发例子及文档

    了解如何创建SNMP会话、发送GET、SET请求、接收TRAP、定义PDU(协议数据单元)以及处理响应是使用SNMP4j的关键。 5. **实例源码分析**:压缩包中的实例源码可以帮助你直观地理解SNMP4j的用法。通过阅读和运行这些...

    snmp4j-1.10.1.rar_Free!_java snmp_snmp4j 1.10_snmp4j 1.10.1

    SNMP4J 1.10.1支持多种操作类型,如GET、SET、GETNEXT、GETBULK等,这些操作可以用于获取、修改或遍历网络设备的状态信息。 2. **SNMP版本支持** SNMP4J 1.10.1支持SNMPv1、v2c和v3三个主要版本。SNMPv1是最基础...

    snmptest测试工具

    2. **GET和SET操作**:snmptest可以通过GET请求获取设备的MIB对象值,通过SET请求修改这些值。MIB(Management Information Base)是SNMP管理的信息结构,包含设备的各种配置和状态信息。 3. **Trap发送**:snmp...

    SNMP测试工具,snmp tester

    用户可以通过该工具查询(GET)和设置(SET)MIB对象的值,验证设备的响应并确保配置正确。这在配置变更后或设备故障排查时非常有用。 4. **陷阱(Trap)测试**: SNMP Trap是设备向管理站发送的异步通知,通常...

    SNMP协议的开源Java实现

    使用SNMP4J库来实现SNMP协议,首先需要理解其核心类,如`Session`用于建立和管理与SNMP设备的连接,`Target`定义了要通信的目标设备,`PDU`(Protocol Data Unit)承载了SNMP消息的数据部分。通过`CommandResponder`...

    Snmp4j-API文档.rar

    6. **事件处理**:Snmp4j使用事件驱动的模型,通过注册`CommandResponder`和`NotificationOriginator`监听器,可以处理SNMP响应和发送自定义陷阱。 7. **PDU和VariableBinding**:`PDU`类是SNMP报文的数据单元,...

    snmp开发入门基础

    SNMP由一系列标准定义,包括管理信息结构(MIB)、协议操作(GET、SET、Trap)和版本(v1、v2c、v3)。 2. SNMP版本: - SNMPv1:最初版本,安全性较低,仅支持明文传输。 - SNMPv2c:增强了SNMPv1,增加了更多陷阱...

    snmp 编程(c#)

    协议操作则定义了管理站与代理(被管理设备)之间的通信方式,如GET、SET和TRAP;管理站是执行管理任务的实体,通常是一个服务器或工作站。 在C#中实现SNMP功能,首先需要了解SNMP版本。SNMP有V1、V2c和V3三个版本...

    snmp/snmp++协议基础入门

    8. **学习资源**:提供的电子书和文档可以帮助初学者理解SNMP的基本概念和工作原理,以及如何使用SNMP++进行程序开发。 总的来说,SNMP协议和SNMP++是网络管理领域的核心工具,它们为网络设备的监控和自动化管理...

    JAVA基于SNMP网络设备MIB信息采集.zip

    4. **异步和同步请求**:SNMP4J支持异步和同步请求模式。异步模式下,你可以注册回调函数处理响应,这对于处理多个并发请求很有用。同步模式则直接返回响应,适合简单的单次请求。 5. **陷阱(Trap)处理**:SNMP...

    基于C#编写的通过OID获取SNMP

    这个库包含了SNMP的所有主要操作,如GET、SET和TRAP。首先,我们需要添加SnmpSharpNet库到项目中,可以通过NuGet包管理器安装。 在编写C#代码时,以下是一般步骤: 1. **导入库**:引入SnmpSharpNet命名空间。 ```...

    snmp C#开发库

    接下来,你可以使用`Get`或`Set`方法来发送请求,并通过事件处理程序接收响应。 以下是一个简单的示例,展示了如何使用SnmpSharpNet库发送一个SNMP GET请求: ```csharp using SnmpSharpNet; // 创建Snmp对象,...

Global site tag (gtag.js) - Google Analytics