package com.wgcloud.util; import com.wgcloud.entity.SnmpInfo; import com.wgcloud.entity.SnmpInterfaceInfo; import com.wgcloud.util.staticvar.StaticKeys; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.snmp4j.*; import org.snmp4j.event.ResponseEvent; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.security.SecurityLevel; import org.snmp4j.security.SecurityModel; import org.snmp4j.smi.*; import org.snmp4j.transport.DefaultUdpTransportMapping; import java.io.IOException; import java.net.InetAddress; import java.util.*; /** * @version V1.0 * @ClassName:SnmpUtil.java * @author: wgcloud * @date: 2022年4月10日 * @Description: snmp监测工具类 * @Copyright: 2019-2021 wgcloud. All rights reserved. */ public class SnmpUtil { private static final Logger logger = LoggerFactory.getLogger(SnmpUtil.class); /** * 设定CommunityTarget * * @param ip 设备IP * @param community 团体名称 * @param port snmp服务的端口号,默认161 * @param snmpVersion snmp版本,0对应version1,1对应version2c,3对应version3 * @return */ public static Target createDefault(String ip, String community, String port, int snmpVersion) { if (StringUtils.isBlank(ip)) { logger.error("ip is null."); return null; } if (StringUtils.isBlank(community)) { logger.error("community is null."); return null; } //定义远程主机的地址 Address address = GenericAddress.parse("udp:" + ip + "/" + port); //设定CommunityTarget Target target = null; //设置使用的snmp版本 begin if (snmpVersion == SnmpConstants.version3) { target = new UserTarget(); //snmpV3需要设置安全级别和安全名称,其中安全名称是创建snmp指定user设置的new OctetString("SNMPV3") target.setSecurityLevel(SecurityLevel.AUTH_PRIV); target.setSecurityName(new OctetString(community)); } else { //snmpV1和snmpV2需要指定团体名名称 target = new CommunityTarget(); ((CommunityTarget) target).setCommunity(new OctetString(community)); if (snmpVersion == SnmpConstants.version2c) { target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c); } } target.setVersion(snmpVersion); //设置使用的snmp版本 end // 设定机器的地址 target.setAddress(address); //设置超时的时间,毫秒 target.setTimeout(15000); //设置超时重试次数 target.setRetries(2); return target; } /** * 处理snmp设备集合,标注设备是否在线,返回MAP集合 * * @param snmpInfoAllList * @return */ public static Map getOnLineList(List snmpInfoAllList) { Map resultMap = new HashMap<>(); Set set = new HashSet<>(); for (SnmpInfo snmpInfo : snmpInfoAllList) { set.add(snmpInfo.getHostname()); } for (String hostName : set) { if (!isEthernetConnection(hostName)) { resultMap.put(hostName, StaticKeys.DOWN_STATE); } else { resultMap.put(hostName, StaticKeys.ON_STATE); } } logger.info("snmp设备在线集合:" + resultMap.toString()); return resultMap; } /** * 测网络通不通 类似 ping ip,通的话返回true,不通返回false * * @param ip * @return * @throws IOException */ public static boolean isEthernetConnection(String ip) { try { InetAddress ad = InetAddress.getByName(ip); // 测试是否可以达到该地址 3秒超时 boolean state = ad.isReachable(3000); return state; } catch (Exception e) { logger.error("isEthernetConnection错误", e); } return false; } /** * 获取设备流量累积和平均值 * * @param snmpInfo * @return */ public static SnmpInfo getAvgSnmpInfo(SnmpInfo snmpInfo) { SnmpInfo snmpInfo2 = new SnmpInfo(); try { /*if (!isEthernetConnection(snmpInfo.getHostname())) { return null; }*/ SnmpInfo snmpInfo1 = SnmpUtil.snmpGet(snmpInfo); long beginBytesRecv = Long.valueOf(snmpInfo1.getBytesRecv()); long beginBytesSent = Long.valueOf(snmpInfo1.getBytesSent()); //暂停3秒,再次获取流量,然后计算平均值 Thread.sleep(3000); snmpInfo2 = SnmpUtil.snmpGet(snmpInfo); long endBytesRecv = Long.valueOf(snmpInfo2.getBytesRecv()); long endBytesSent = Long.valueOf(snmpInfo2.getBytesSent()); double recvAvg = (endBytesRecv - beginBytesRecv) / (double) 3; double sentAvg = (endBytesSent - beginBytesSent) / (double) 3; snmpInfo2.setRecvAvg(FormatUtil.formatDouble(recvAvg, 2) + ""); snmpInfo2.setSentAvg(FormatUtil.formatDouble(sentAvg, 2) + ""); //CPU使用率% = 100 - 空闲CPU使用率% if (!StringUtils.isEmpty(snmpInfo.getCpuPerOID())) { double cpuPer = 100 - Double.valueOf(snmpInfo2.getCpuPer()); snmpInfo2.setCpuPer(FormatUtil.formatDouble(cpuPer, 2) + ""); } else { snmpInfo2.setCpuPer("0"); } //计算内存使用率% begin if (!StringUtils.isEmpty(snmpInfo.getMemSizeOID()) && !StringUtils.isEmpty(snmpInfo.getMemTotalSizeOID())) { long memSize = Long.valueOf(snmpInfo2.getMemSize()); long memTotalSize = Long.valueOf(snmpInfo2.getMemTotalSize()); snmpInfo2.setMemPer(FormatUtil.formatDouble(((double) memSize / memTotalSize) * 100, 2) + ""); } else { snmpInfo2.setMemPer("0"); } //计算内存使用率% end return snmpInfo2; } catch (Exception e) { logger.error("getAvgSnmpInfo错误", e); snmpInfo2.setRecvAvg("0"); snmpInfo2.setSentAvg("0"); snmpInfo2.setMemSize("0"); snmpInfo2.setMemTotalSize("1"); snmpInfo2.setCpuPer("0"); snmpInfo2.setMemPer("0"); } return snmpInfo2; } /** * 获取接口信息 * * @param snmpInfo * @return */ public static List getInterfaceSnmpInfo(SnmpInfo snmpInfo) { //接口名称OID String interfaceNameOID = snmpInfo.getInterfaceNameOID(); //接口状态 OID String interfaceStatusOID = snmpInfo.getInterfaceStatusOID(); //速率 OID String actualSpeedOID = snmpInfo.getActualSpeedOID(); //工作模式OID String workMTUOID = snmpInfo.getWorkMTUOID(); //双工模式OID String actualMTUOID = snmpInfo.getActualMTUOID(); //环回检测 OID String loopbackOID = snmpInfo.getLoopbackOID(); //描述OID String descriptionOID = snmpInfo.getDescriptionOID(); List> interfaceStatusList = new ArrayList<>(); List> interfaceNameList = new ArrayList<>(); List> actualSpeedList = new ArrayList<>(); List> workMTUList = new ArrayList<>(); List> actualMTUList = new ArrayList<>(); List> loopbackList = new ArrayList<>(); List> descriptionList = new ArrayList<>(); List interfaceInfos = new ArrayList<>(); if(StringUtils.isNotEmpty(interfaceNameOID)){ interfaceNameList = snmpGetInterface(snmpInfo, interfaceNameOID); } if(StringUtils.isNotEmpty(interfaceStatusOID)){ interfaceStatusList = snmpGetInterface(snmpInfo, interfaceStatusOID); } if(StringUtils.isNotEmpty(actualSpeedOID)){ actualSpeedList = snmpGetInterface(snmpInfo, actualSpeedOID); } if(StringUtils.isNotEmpty(workMTUOID)){ workMTUList = snmpGetInterface(snmpInfo, workMTUOID); } if(StringUtils.isNotEmpty(actualMTUOID)){ actualMTUList = snmpGetInterface(snmpInfo, actualMTUOID); } if(StringUtils.isNotEmpty(loopbackOID)){ loopbackList = snmpGetInterface(snmpInfo, loopbackOID); } if(StringUtils.isNotEmpty(descriptionOID)){ descriptionList = snmpGetInterface(snmpInfo, descriptionOID); } if (interfaceNameList.size() >0 ){ for (int i = 0; i < interfaceNameList.size(); i++) { Map stringObjectMap = interfaceNameList.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { SnmpInterfaceInfo snmpInterfaceInfo = new SnmpInterfaceInfo(); snmpInterfaceInfo.setId(UUIDUtil.getUUID()); snmpInterfaceInfo.setCreateTime(new Date()); snmpInterfaceInfo.setHostname(snmpInfo.getHostname()); snmpInterfaceInfo.setInterfaceName(stringObjectEntry.getValue().toString().trim()); interfaceInfos.add(snmpInterfaceInfo); } } } if(interfaceStatusList.size() > 0){ for (int i = 0; i < interfaceStatusList.size(); i++) { Map stringObjectMap = interfaceStatusList.get(i); SnmpInterfaceInfo snmpInterfaceInfo = interfaceInfos.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { try { snmpInterfaceInfo.setIsUp(Integer.parseInt(stringObjectEntry.getValue().toString().trim())); }catch (Exception e){ snmpInterfaceInfo.setIsUp(0); e.printStackTrace(); } } } } if (actualSpeedList.size()>0){ for (int i = 0; i < actualSpeedList.size(); i++) { Map stringObjectMap = actualSpeedList.get(i); SnmpInterfaceInfo snmpInterfaceInfo = interfaceInfos.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { try { snmpInterfaceInfo.setActualSpeed(Long.parseLong(stringObjectEntry.getValue().toString().trim())); }catch (Exception e){ snmpInterfaceInfo.setActualSpeed(100000L); e.printStackTrace(); } } } } if (workMTUList.size()>0){ for (int i = 0; i < workMTUList.size(); i++) { Map stringObjectMap = workMTUList.get(i); SnmpInterfaceInfo snmpInterfaceInfo = interfaceInfos.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { try { snmpInterfaceInfo.setWorkMTU(Integer.parseInt(stringObjectEntry.getValue().toString().trim())); }catch (Exception e){ snmpInterfaceInfo.setWorkMTU(1500); e.printStackTrace(); } } } } if (actualMTUList.size()>0){ for (int i = 0; i < actualMTUList.size(); i++) { Map stringObjectMap = actualMTUList.get(i); SnmpInterfaceInfo snmpInterfaceInfo = interfaceInfos.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { try { snmpInterfaceInfo.setActualMTU(Integer.parseInt(stringObjectEntry.getValue().toString().trim())); }catch (Exception e){ snmpInterfaceInfo.setActualMTU(1500); e.printStackTrace(); } } } } if (loopbackList.size()>0){ for (int i = 0; i < loopbackList.size(); i++) { Map stringObjectMap = loopbackList.get(i); SnmpInterfaceInfo snmpInterfaceInfo = interfaceInfos.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { try { snmpInterfaceInfo.setLoopback(Integer.parseInt(stringObjectEntry.getValue().toString().trim())); }catch (Exception e){ snmpInterfaceInfo.setLoopback(0); e.printStackTrace(); } } } } if (descriptionList.size()>0){ for (int i = 0; i < descriptionList.size(); i++) { Map stringObjectMap = descriptionList.get(i); SnmpInterfaceInfo snmpInterfaceInfo = interfaceInfos.get(i); for (Map.Entry stringObjectEntry : stringObjectMap.entrySet()) { try { snmpInterfaceInfo.setDescription(stringObjectEntry.getValue().toString().trim()); }catch (Exception e){ e.printStackTrace(); } } } } return interfaceInfos; } /** * snmpGet方式 获取交换机设备的发送、接收流量数据 */ public static SnmpInfo snmpGet(SnmpInfo snmpInfo) { Snmp snmp = null; TransportMapping transport = null; SnmpInfo snmpInfoRes = new SnmpInfo(); Vector vector = null; try { //设备IP String ip = snmpInfo.getHostname(); //团体名称 String community = snmpInfo.getSnmpCommunity(); //snmp服务的端口号,默认161 String port = snmpInfo.getSnmpPort(); //snmp版本,0对应version1,1对应version2c,3对应version3 int snmpVersion = Integer.valueOf(snmpInfo.getSnmpVersion()); //上行出口流量字节数 OID String sendOID = snmpInfo.getSentOID(); //下行入口流量字节数 OID String receiveOID = snmpInfo.getRecvOID(); //空闲%CPU使用率 OID String cpuPerOID = snmpInfo.getCpuPerOID(); //内存已使用大小 OID String memSizeOID = snmpInfo.getMemSizeOID(); //内存总大小 OID String memTotalSizeOID = snmpInfo.getMemTotalSizeOID(); if (StringUtils.isEmpty(sendOID) || StringUtils.isEmpty(receiveOID)) { snmpInfoRes.setBytesSent("0"); snmpInfoRes.setBytesRecv("0"); } if (StringUtils.isEmpty(cpuPerOID)) { snmpInfoRes.setCpuPer("100"); } if (StringUtils.isEmpty(memSizeOID)) { snmpInfoRes.setMemSize("0"); } if (StringUtils.isEmpty(memTotalSizeOID)) { snmpInfoRes.setMemTotalSize("1"); } //设定CommunityTarget Target myTarget = createDefault(ip, community, port, snmpVersion); // 设定采取的协议 // 设定传输协议为UDP transport = new DefaultUdpTransportMapping(); // 调用TransportMapping中的listen()方法,启动监听进程,接收消息,由于该监听进程是守护进程,最后应调用close()方法来释放该进程 transport.listen(); // 创建SNMP对象,用于发送请求PDU snmp = new Snmp(transport); // 创建请求pdu,获取mib PDU request = new PDU(); // 调用的add方法绑定要查询的OID //上行,端口出口流量(byte),绑定多个OID String[] sendOIDs = sendOID.split(StaticKeys.SPLIT_ENTER); for (String sendOIDTmp : sendOIDs) { request.add(new VariableBinding(new OID(sendOIDTmp.trim()))); } //下行,端口入口流量(byte),绑定多个OID String[] receiveOIDs = receiveOID.split(StaticKeys.SPLIT_ENTER); for (String receiveOIDTmp : receiveOIDs) { request.add(new VariableBinding(new OID(receiveOIDTmp.trim()))); } //绑定空闲cpu使用率OID if (!StringUtils.isEmpty(cpuPerOID)) { request.add(new VariableBinding(new OID(cpuPerOID.trim()))); } //绑定内存已使用大小OID和内存总大小OID if (!StringUtils.isEmpty(memSizeOID) && !StringUtils.isEmpty(memTotalSizeOID)) { request.add(new VariableBinding(new OID(memSizeOID.trim()))); request.add(new VariableBinding(new OID(memTotalSizeOID.trim()))); } // 调用setType()方法来确定该pdu的类型 request.setType(PDU.GET); // 调用 send(PDU pdu,Target target)发送pdu,返回一个ResponseEvent对象 ResponseEvent responseEvent = snmp.send(request, myTarget); // 通过ResponseEvent对象来获得SNMP请求的应答pdu,方法:public PDU getResponse() PDU response = responseEvent.getResponse(); vector = response.getVariableBindings(); long bytesSentSum = 0; long bytesRecvSum = 0; // 通过应答pdu获得mib信息(之前绑定的OID的值),方法:VaribleBinding get(int index) for (int i = 0; i < vector.size(); i++) { try { VariableBinding vb1 = vector.get(i); if (sendOID.contains(String.valueOf(vb1.getOid()))) { bytesSentSum += Long.valueOf(String.valueOf(vb1.getVariable())); continue; } if (receiveOID.contains(String.valueOf(vb1.getOid()))) { bytesRecvSum += Long.valueOf(String.valueOf(vb1.getVariable())); continue; } if (cpuPerOID.contains(String.valueOf(vb1.getOid()))) { snmpInfoRes.setCpuPer(String.valueOf(vb1.getVariable())); continue; } if (memSizeOID.contains(String.valueOf(vb1.getOid()))) { snmpInfoRes.setMemSize(String.valueOf(vb1.getVariable())); continue; } if (memTotalSizeOID.contains(String.valueOf(vb1.getOid()))) { snmpInfoRes.setMemTotalSize(String.valueOf(vb1.getVariable())); continue; } } catch (Exception e) { logger.error("snmp应答pdu获得mib信息错误", e); } } snmpInfoRes.setBytesSent(String.valueOf(bytesSentSum)); snmpInfoRes.setBytesRecv(String.valueOf(bytesRecvSum)); return snmpInfoRes; } catch (Exception e) { logger.error("snmp检测错误", e); } finally { // 调用close()方法释放该进程 closeTransport(transport); closeSnmp(snmp); } return snmpInfoRes; } /** * WALK方式请求 *功能简介:这个方法是getnext,就是遍历该oid下的所有子节点 */ public static List> snmpGetInterface(SnmpInfo snmpInfo, String oid) { Snmp snmp = null; try { List> list = new ArrayList<>(); //1、初始化snmp,并开启监听 snmp = new Snmp(new DefaultUdpTransportMapping()); //开启监听 snmp.listen(); //2、创建目标对象 Target target = createTarget(snmpInfo.getHostname(),snmpInfo.getSnmpPort(),snmpInfo.getSnmpCommunity()); //3、创建报文 PDU pdu = createPDU(Integer.parseInt(snmpInfo.getSnmpVersion()), PDU.GETNEXT,oid ); //4、发送报文,并获取返回结果 boolean matched = true; while (matched) { ResponseEvent responseEvent = snmp.send(pdu, target); if (responseEvent == null || responseEvent.getResponse() == null) { //LogUtil.info("snmp TimeOut..."); break; } PDU response = responseEvent.getResponse(); String nextOid = null; Vector variableBindings = response.getVariableBindings(); for (int i = 0; i < variableBindings.size(); i++) { VariableBinding variableBinding = variableBindings.elementAt(i); Variable variable = variableBinding.getVariable(); nextOid = variableBinding.getOid().toDottedString(); //如果不是这个节点下的oid则终止遍历,否则会输出很多,直到整个遍历完。 if (!nextOid.startsWith(oid)) { matched = false; break; } Map map = new HashMap(); //放入oid以及oid对应获得的值 map.put(nextOid,variable); list.add(map); } if (!matched) { break; } pdu.clear(); pdu.add(new VariableBinding(new OID(nextOid))); } System.out.println("list的大小 = " +list.size()); System.out.println(list); return list; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private static PDU createPDU(int version, int type, String oid) { PDU pdu = null; if (version == SnmpConstants.version3) { pdu = new ScopedPDU(); } else { pdu = new PDUv1(); } pdu.setType(type); pdu.add(new VariableBinding(new OID(oid.trim()))); // //接口状态OID // if (!StringUtils.isEmpty(actualSpeedOID)) { // pdu.add(new VariableBinding(new OID(interfaceStatusOID.trim()))); // } // //绑定速率 OID // if (!StringUtils.isEmpty(actualSpeedOID)) { // pdu.add(new VariableBinding(new OID(actualSpeedOID.trim()))); // } // //工作模式OID // if (!StringUtils.isEmpty(workMTUOID)) { // pdu.add(new VariableBinding(new OID(workMTUOID.trim()))); // } // //双工模式OID // if (!StringUtils.isEmpty(actualMTUOID)) { // pdu.add(new VariableBinding(new OID(actualMTUOID.trim()))); // } // //环回检测 OID // if (!StringUtils.isEmpty(loopbackOID)) { // pdu.add(new VariableBinding(new OID(loopbackOID.trim()))); // } // //描述OID // if (!StringUtils.isEmpty(descriptionOID)) { // pdu.add(new VariableBinding(new OID(descriptionOID.trim()))); // } return pdu; } private static Target createTarget(String hostIp, String port, String community) { //先得到连接的ip和端口号 String addressGet = "udp:" + hostIp+"/"+port; Target target = null; int version = 1; if (!(version == SnmpConstants.version3 || version == SnmpConstants.version2c || version == SnmpConstants.version1)) { return target; } // if (version == SnmpConstants.version3) { // target = new UserTarget(); // //snmpV3需要设置安全级别和安全名称,其中安全名称是创建snmp指定user设置的new OctetString("SNMPV3") // target.setSecurityLevel(SecurityLevel.AUTH_PRIV); // target.setSecurityName(new OctetString(this.username)); // } else { //snmpV1和snmpV2需要指定团体名名称 target = new CommunityTarget(); ((CommunityTarget) target).setCommunity(new OctetString(community)); if (version == SnmpConstants.version2c) { target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c); } } target.setVersion(version); //必须指定,没有设置就会报错。 target.setAddress(GenericAddress.parse(addressGet)); target.setRetries(3); target.setTimeout(2000); return target; } /** * 调用close()方法释放该进程 * * @param transport */ private static void closeTransport(TransportMapping transport) { try { if (null != transport) { transport.close(); } } catch (Exception e) { logger.error("closeTransport错误", e); } } /** * 关闭snmp * * @param snmp */ private static void closeSnmp(Snmp snmp) { try { if (null != snmp) { snmp.close(); } } catch (Exception e) { logger.error("closeSnmp错误", e); } } public static void main(String[] args) { SnmpInfo snmpInfo = new SnmpInfo(); snmpInfo.setHostname("192.168.8.150"); snmpInfo.setSnmpCommunity("public"); snmpInfo.setSnmpVersion("1"); snmpInfo.setSnmpPort("161"); snmpInfo.setInterfaceNameOID("1.3.6.1.2.1.31.1.1.1.1"); snmpInfo.setInterfaceStatusOID("1.3.6.1.2.1.2.2.1.8"); snmpInfo.setActualSpeedOID("1.3.6.1.2.1.2.2.1.5"); snmpInfo.setActualMTUOID("1.3.6.1.2.1.10.7.2.1.19"); snmpInfo.setDescriptionOID("1.3.6.1.2.1.2.2.1.2"); List> maps = snmpGetInterface(snmpInfo, snmpInfo.getDescriptionOID()); for (Map map : maps) { for (Map.Entry stringObjectEntry : map.entrySet()) { Object value = stringObjectEntry.getValue(); System.out.println(value); } } } }