作者:坑爹的马_782 | 来源:互联网 | 2023-09-23 07:04
以下可以应用于:Linux、Windows、Mac系统。
我因为网上的文章走了很多弯路,这里如果只是做监听,不需要开启SNMP服务,只需要看下面的代码即可,如果是发出告警是需要开启SNMP服务的。
实现时有以下几个问题需要注意:
1.VMware中配置的SNMP接收方IP和端口,这里的IP是你程序所在服务器的IP,端口一般是162。
注意:要遵循1024 以下的端口要用root启动,这个是windows、Linux、mac通用原则
2.如果本地只是监听消息,不发出消息的话,本地不需要开启SNMP服务。
3.SNMP发出的消息都是通过MIB文件来翻译的,根据OID号来找到对应的消息,即可得到想要的消息,MIB文件也不需要导入到程序中,只需要做对应即可。
在pom.xml文件中引入snmp4j包,如下
org.snmp4jsnmp4j2.8.2
以下是代码实现:
import java.io.IOException;
import com.alibaba.fastjson.JSON;
import com.fit2cloud.commons.utils.LogUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcher;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.PrivAES128;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;public class SnmpTrapHandler implements CommandResponder{private static Logger log = LoggerFactory.getLogger(SnmpTrapHandler.class);private static int threadNum = 200;//这里的ip是指程序所在IP,这里是:192.168.0.1//1162指的是端口号,因为162需要root权限,所以测试的时候我用1162端口,需要两边的IP和端口保持一致private static String ipAddress = "udp:192.168.0.1/1162";private Snmp snmp = null;public void init(){//1、初始化多线程消息转发类ThreadPool threadPool = ThreadPool.create("SnmpTrap", threadNum);MessageDispatcher messageDispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());//其中要增加三种处理模型。如果snmp初始化使用的是Snmp(TransportMapping extends Address> transportMapping) ,就不需要增加messageDispatcher.addMessageProcessingModel(new MPv1());messageDispatcher.addMessageProcessingModel(new MPv2c());OctetString localEngineID = new OctetString(MPv3.createLocalEngineID());USM usm = new USM(SecurityProtocols.getInstance().addDefaultProtocols(), localEngineID, 0);UsmUser user = new UsmUser(new OctetString("SNMPV3"), AuthSHA.ID, new OctetString("authPassword"),PrivAES128.ID, new OctetString("privPassword"));usm.addUser(user.getSecurityName(), user);messageDispatcher.addMessageProcessingModel(new MPv3(usm));//2、创建transportMappingTransportMapping> transportMapping = null;try {UdpAddress updAddr = (UdpAddress) GenericAddress.parse(System.getProperty("snmp4j.listenAddress", ipAddress));transportMapping = new DefaultUdpTransportMapping(updAddr);//3、正式创建snmpsnmp = new Snmp(messageDispatcher, transportMapping);//开启监听snmp.listen();} catch (IOException e) {log.error("初始化transportMapping失败:", e.getMessage());e.printStackTrace();}}public void start() {init();//一定要将当前对象添加至commandResponderListeners中snmp.addCommandResponder(this);System.out.println("开始监听trap信息:");}/*** 处理信息方法*/@Overridepublic void processPdu(CommandResponderEvent event) {String version = null ;String community = null;LogUtil.info("接收到的告警信息:"+ JSON.toJSONString(event));if (event.getPDU().getType() == PDU.V1TRAP) {version = "v1";community = new String(event.getSecurityName());} else if (event.getPDU().getType() == PDU.TRAP){if (event.getSecurityModel() == 2) {version = "v2";community = new String(event.getSecurityName());}else {version = "v3";}}System.out.println("接收到的trap信息:[发送来源="+event.getPeerAddress()+",snmp版本="+version+",团体名="+community+", 携带的变量="+event.getPDU().getVariableBindings()+"]");}public static void main(String[] args) {SnmpTrapHandler handler = new SnmpTrapHandler();handler.start();}
}