Java实现Snmp

Java实现Snmp

本文基于Java实现了snmp同步发送消息,及模拟了snmp的代理端(虚拟设备),对接收的snmp消息进行回复。直接上代码。

snmp客户端代码:

/**
 * Snmp采集器
 * 
 * @author Fan
 *
 */
public class SnmpCollector {

	private final short targetPort = 161;
	private final short listenPort = 162;
	private Snmp snmp;
	private String targetIp;

	public SnmpCollector(String targetIp) {
		this.targetIp = targetIp;
		init();
	}

	private void init() {
		try {
			// 使用本地IP和162端口号, 选择UDP发送方式
			this.snmp = new Snmp(new DefaultUdpTransportMapping(new UdpAddress(listenPort)));
			// 添加自定义消息处理
			snmp.addCommandResponder(new TripResponser());
			snmp.listen();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 发送snmp消息
	 * @param pdu
	 * @return
	 * @throws IOException
	 */
	public ResponseEvent send(PDU pdu) throws IOException {
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString("public"));//设置团体名
		target.setVersion(SnmpConstants.version2c);//设置SNMP的版本
		target.setTimeout(TimeUnit.SECONDS.toMillis(2));
		try {
			target.setAddress(new UdpAddress(InetAddress.getByName(targetIp), targetPort));
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		return this.snmp.send(pdu, target);
	}

	/**
	 * SNMP trip处理类
	 * @author Fan
	 *
	 */
	private class TripResponser implements CommandResponder {

		@Override
		public void processPdu(CommandResponderEvent event) {
			System.out.println("reveice the trip!!!");
		}

	}
}

snmp代理端(虚拟设备端)代码:

/**
 * Snmp代理类
 * 
 * @author Fan
 *
 */
public class SnmpAgent {

	private final short targetPort = 162;// 发送端口号
	private final short listenPort = 161;// 本地监听端口号
	private Snmp snmp;

	public SnmpAgent() {
		init();
	}

	/**
	 * 初始化snmp
	 */
	private void init() {
		UdpAddress udpAddress = null;
		try {
			// 使用本地IP和161端口号
			udpAddress = new UdpAddress(InetAddress.getLocalHost(), listenPort);
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		try {
			// 选择UDP发送方式
			this.snmp = new Snmp(new DefaultUdpTransportMapping(udpAddress));
			// 设置snmp的消息处理模型 MPv2c代表SNMPv2c(基于社区的SNMPv2)
			snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
			// 添加自定义消息处理
			snmp.addCommandResponder(new ReceiveResponder());
			snmp.listen();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 多线程接收消息
	 */
	private void init2() {
		ThreadPool pool = ThreadPool.create("snmpReceiver", 1);
		MultiThreadedMessageDispatcher dispatcher = new MultiThreadedMessageDispatcher(pool,
				new MessageDispatcherImpl());
		try {
			DefaultUdpTransportMapping transportMapping = new DefaultUdpTransportMapping(
					new UdpAddress(InetAddress.getLocalHost(), listenPort));
			this.snmp = new Snmp(dispatcher, transportMapping);
			snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
			this.snmp.listen();
			this.snmp.addCommandResponder(new ReceiveResponder());

		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 自定义消息处理类
	 * 
	 * @author Fan
	 *
	 */
	private class ReceiveResponder implements CommandResponder {

		@Override
		public void processPdu(CommandResponderEvent event) {
			System.out.println("收到对方消息:" + event.toString());
			PDU pdu = event.getPDU();
			if (pdu == null) {
				return;
			}
			if (pdu.getType() == PDU.GET) {
				doGetResponse(pdu.getVariableBindings());
			}

			pdu.setType(PDU.RESPONSE);
			StatusInformation statusInfo = new StatusInformation();
			StateReference reference = event.getStateReference();
			try {
				// 响应snmp消息
				event.getMessageDispatcher().returnResponsePdu(event.getMessageProcessingModel(),
						event.getSecurityModel(), event.getSecurityName(), event.getSecurityLevel(), pdu,
						event.getMaxSizeResponsePDU(), reference, statusInfo);
			} catch (MessageException e) {
				e.printStackTrace();
			}
		}

		/**
		 * 对接收的消息设置返回值
		 * 
		 * @param bindings
		 */
		private void doGetResponse(Vector<? extends VariableBinding> bindings) {
			for (VariableBinding varBin : bindings) {
				System.out.println("接收到的OID是:" + varBin.getOid().toString());
				varBin.setVariable(new Integer32(1));
				System.out.println("给客户端回复的值是:" + varBin.getVariable().toInt());
			}
		}

	}

	public ResponseEvent send(PDU pdu) throws IOException {
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString("public"));
		target.setVersion(SnmpConstants.version2c);
		target.setTimeout(TimeUnit.SECONDS.toMillis(2));
		try {
			target.setAddress(new UdpAddress(InetAddress.getLocalHost(), targetPort));
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		return this.snmp.send(pdu, target);
	}

	private static PDU createTrip() {
		PDU pdu = new PDU();
		pdu.setType(PDU.TRAP);
		VariableBinding vb = new VariableBinding(new OID("1.3.6.1.2.1.3.4.1.1"));
		vb.setVariable(new Integer32(34));
		pdu.add(vb);
		return pdu;
	}

	public static void main(String[] args) throws InterruptedException {
		SnmpAgent agent = new SnmpAgent();
		System.out.println("snmp-agent started...");

		Thread.sleep(5000);

		 try {
		 // trip测试
		 agent.send(createTrip());
		
		 System.out.println("send trip success-------");
		 } catch (IOException e) {
		 e.printStackTrace();
		 }

		/**
		 * 让主线程一直处理等待中,因为DefaultUdpTransportMapping中监听本地(161端口)的线程为守护线程,
		 * 一旦主线程运行完毕,守护线程也随即销毁 如果采用多线程方式启动(如调用 init2方法),则不需要主线程等待,但会额外开启新的线程。所以,视情况而定
		 */
		synchronized (agent) {
			agent.wait();
		}
		
	}

}

测试端代码:

/**
 * snmp测试
 * @author Fan
 *
 */
public class SnmpTest {

	public static void main(String[] args) {

		SnmpCollector collector = new SnmpCollector("192.168.0.102");
		PDU pdu = new PDU();
		pdu.setType(PDU.GET);
		pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.3.4.1")));
		
		try {
			ResponseEvent event = collector.send(pdu);
			PDU response = event.getResponse();
			if (response == null) {
				System.out.println("未能采集到设备信息");
				return;
			} 
			Vector<? extends VariableBinding> bindings = response.getVariableBindings();
			for (VariableBinding var : bindings) {
				System.out.println("发送的OID是:" + var.getOid().toString());
				System.out.println("采集的值是:" + var.getVariable().toInt());
			}
			
			
		} catch (IOException e) {
			e.printStackTrace();
		}
//		while(true) {
//			try {
//				Thread.sleep(TimeUnit.SECONDS.toMillis(3));
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//			System.out.println("over!");
//		}
		
	}

}

先启动SnmpAgent,再启动SnmpTest,测试结果如下:

在这里插入图片描述在这里插入图片描述

  • 13
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Java中,可以使用snmp4j库来实现SNMP的集成。snmp4j是一个开源的Java库,提供了SNMP协议的实现,可以用于开发SNMP管理应用程序。 以下是在Java中集成SNMP的基本步骤: 1. 引入snmp4j库:首先,需要在Java项目中引入snmp4j库。可以通过将snmp4j的jar文件添加到项目的类路径中来实现。 2. 创建SNMP管理器:使用snmp4j库提供的类和方法,创建一个SNMP管理器对象。SNMP管理器用于与SNMP代理设备进行通信。 ```java import org.snmp4j.Snmp; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.CommunityTarget; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.UdpAddress; // 创建SNMP管理器 Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); ``` 3. 设置SNMP代理信息:配置SNMP代理设备的相关信息,如IP地址、端口号、SNMP团体字符串等。 ```java // 设置SNMP代理信息 CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("public")); // SNMP团体字符串 target.setAddress(new UdpAddress("192.168.0.1/161")); // SNMP代理设备的IP地址和端口号 target.setVersion(SnmpConstants.version2c); // SNMP版本(这里使用SNMPv2c) ``` 4. 发送SNMP请求:使用SNMP管理器对象发送SNMP请求,并获取响应。 ```java // 发送SNMP GET请求 PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1.0"))); // OID为系统描述信息 pdu.setType(PDU.GET); ResponseEvent response = snmp.send(pdu, target); // 获取响应结果 if (response != null && response.getResponse() != null) { PDU responsePDU = response.getResponse(); if (responsePDU.getErrorStatus() == PDU.noError) { System.out.println("System Description = " + responsePDU.getVariableBindings().firstElement().getVariable()); } else { System.err.println("Error: " + responsePDU.getErrorStatusText()); } } ``` 通过以上步骤,可以实现Java中集成SNMP,发送SNMP请求并获取响应。需要根据具体的需求,配置合适的SNMP请求类型、OID等参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值