java通過snmp協(xié)議獲取物理設(shè)備信息
一、SNMP簡介
1、什么是snmp
snmp中文含義是簡單網(wǎng)絡(luò)管理協(xié)議,可用完成對計(jì)算機(jī)、路由器和其他網(wǎng)絡(luò)設(shè)備的遠(yuǎn)程管理和監(jiān)視。利用 SNMP 協(xié)議可以更好地管理和監(jiān)控網(wǎng)絡(luò)。管理工作站可以遠(yuǎn)程管理所有支持該協(xié)議的網(wǎng)絡(luò)設(shè)備,如監(jiān)視網(wǎng)絡(luò)狀態(tài)、修改網(wǎng)絡(luò)設(shè)備配置、接收網(wǎng)絡(luò)事件警告等。
通俗的講: 我們可用通過snmp協(xié)議獲取物理機(jī)、存儲服務(wù)器、交換機(jī)等設(shè)備的信息,本文我們是通過java程序來獲取。
二、SNMP獲取信息步驟
1、開啟SNMP
首先,我們需要在對應(yīng)的設(shè)備上開啟snmp協(xié)議,不同的設(shè)備可自行百度開啟的方法。一般設(shè)備有對應(yīng)的管理軟件,可從管理軟件開啟snmp。
開啟snmp需要注意兩個地方:
1、開啟時會讓你設(shè)置團(tuán)體名,一般填pulic就行。
2、端口默認(rèn)162。
2、MIB文件
舉例說明,獲取任何一類設(shè)備信息,都需要該類設(shè)備對應(yīng)的MIB文件,從MIB文件中解析出OID,每個OID對應(yīng)一個指標(biāo)。使用cpu核數(shù)對應(yīng)的OID才能獲取核數(shù)的個數(shù)。
注意:mib文件獲取方式
1、打設(shè)備廠商客服電話獲取。
2、去githup下載: mib鏈接,下載后不確定哪個MIB文件是我們需要的,只能用mib瀏覽器自己試唄。
3、MIB瀏覽器
mib瀏覽器就相當(dāng)于一個客戶端,用來解析mib文件,可以使用該瀏覽器模擬snmp請求獲取對應(yīng)的指標(biāo)信息。
我是用瀏覽器先測試請求可不可用,然后在從瀏覽器上拿到oid用java程序獲取。

三、java獲取SNMP信息
1、引入maven
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.8.3</version>
</dependency>2、代碼實(shí)現(xiàn)
注:代碼種有snmpGet、snmpWalk兩個方法可用獲取snmp信息。
snmpGet:是傳入的哪個OID的值,就獲取該OID的值。
snmpWalk:獲取OID的子OID的值。舉例說明,傳入的OID是1.2.3.4。 獲取的是1.2.3.4.1,1.2.3.4.2,1.2.3.4.3的OID值。
import lombok.extern.slf4j.Slf4j;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;
import java.io.IOException;
import java.util.*;
@Slf4j
public class SnmpUtil2 {
private static Snmp snmp = null;
private static CommunityTarget target = null;
private static Integer port = 162;
private static String ip = "10.11.83.10";
private static String communityName = "public";
public static void main(String[] args) throws Exception {
new SnmpUtil2(ip, port);
List<TableEvent> tableEvents = snmpWalk("1.3.6.1.4.1.2011.2.235.1.1.15.50.1.12");
for (TableEvent tableEvent : tableEvents) {
VariableBinding[] vb = tableEvent.getColumns();
if (null == vb) {
continue;
}
System.out.println(vb[0].getOid()+"======"+vb[0].getVariable());
}
log.info("=================美麗的分割線===================");
ResponseEvent responseEvent = snmpGet("1.3.6.1.4.1.2011.2.235.1.1.15.50.1.12");
PDU response = responseEvent.getResponse();
for (int i = 0; i < response.size(); i++) {
VariableBinding vb1 = response.get(i);
System.out.println(vb1.getOid().toString() + "===" + vb1.getVariable());
}
}
public SnmpUtil2(String intranetDeviceIp, Integer snmpPort) throws IOException {
if (snmp == null) {
snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
}
//初始化CommunityTarget
target = new CommunityTarget();
target.setCommunity(new OctetString(communityName));
target.setVersion(SnmpConstants.version2c);
target.setAddress(new UdpAddress(intranetDeviceIp + "/" + snmpPort));
target.setTimeout(1000);
target.setRetries(3);
}
private static ResponseEvent snmpGet(String oid) {
PDU pdu = new PDU();
pdu.addOID(new VariableBinding(new OID(oid)));
ResponseEvent re = null;
try {
re = snmp.get(pdu, target);
} catch (Exception e) {
log.error("snmpGet 異常" + e.getMessage());
}
return re;
}
private static List<TableEvent> snmpWalk(String oid) {
TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GETBULK));
OID[] columnOid = new OID[]{new OID(oid)};
return utils.getTable(target, columnOid, null, null);
}
}3、常用OID
用枚舉的方式列了一些常用的OID,包括獲取戴爾華為物理機(jī)CPU、內(nèi)存容量及使用率,戴爾存儲集群,FS8600,SCV3000,PS6210的容量及使用率 具體看下代碼注釋
public enum OidEnum {
//物理機(jī)CPU總核數(shù)、使用率
HostCpuUtilization("1.3.6.1.2.1.25.3.3.1.2","物理機(jī)CPU總核數(shù)和使用率","walk"),
//物理機(jī)內(nèi)存總量
HostMemoryTotal("1.3.6.1.2.1.25.2.2.0","物理機(jī)內(nèi)存總量","get"),
//物理機(jī)內(nèi)存總量(用來計(jì)算內(nèi)存的使用率或者拿到硬盤總量)
HostMemoryTotalCalUtil("1.3.6.1.2.1.25.2.3.1.5","物理機(jī)內(nèi)存總量(用來計(jì)算內(nèi)存的使用率或者拿到硬盤總量)","walk"),
//物理機(jī)內(nèi)存使用率(用來計(jì)算內(nèi)存的使用率或者拿到硬盤使用量)
HostMemoryUsedCalUtil("1.3.6.1.2.1.25.2.3.1.6","物理機(jī)內(nèi)存使用率(用來計(jì)算內(nèi)存的使用率或者拿到硬盤使用量)","walk"),
/**
* 華為物理機(jī)CPU總核數(shù)
*/
HuaWeiHostCpuTotal("1.3.6.1.4.1.2011.2.235.1.1.15.50.1.12","華為物理機(jī)CPU總核數(shù)","walk"),
/**
* 華為物理機(jī)CPU使用率, 單位%
*/
HuaWeiHostCpuUtilization("1.3.6.1.4.1.2011.2.235.1.1.1.23.0","華為物理機(jī)CPU使用率","get"),
/**
* 華為物理機(jī)內(nèi)存總量
*/
HuaWeiHostMemoryTotal("1.3.6.1.4.1.2011.2.235.1.1.16.50.1.4","華為物理機(jī)內(nèi)存總量","walk"),
/**
* 華為物理機(jī)內(nèi)存使用率, 單位%
*/
HuaWeiHostMemoryUtilization("1.3.6.1.4.1.2011.2.235.1.1.1.25.0","華為物理機(jī)內(nèi)存總量","get"),
//scv3000獲得存儲總量
StorageScv3000Total("1.3.6.1.4.1.674.11000.2000.500.1.2.32.1.3", "scv3000獲得存儲總量(單位GB)","walk"),
StorageScv3000Alloc("1.3.6.1.4.1.674.11000.2000.500.1.2.32.1.7", "scv3000獲得存儲分配量(單位GB)","walk"),
StorageScv3000Used("1.3.6.1.4.1.674.11000.2000.500.1.2.32.1.6", "scv3000獲得存儲使用量(單位GB)","walk"),
//PS6210存儲總量
StoragePs6210Total("1.3.6.1.4.1.12740.1.1.2.1.1.1","PS6210存儲總量(單位MB)","get"),
//PS6210存儲空閑量
StoragePs6210Free("1.3.6.1.4.1.12740.1.1.2.1.15.1","PS6210存儲空閑量(單位MB)","get"),
//PS6210存儲使用量
StoragePs6210Used("1.3.6.1.4.1.12740.1.1.2.1.2.1","PS6210存儲已使用(單位MB)","get"),
//FS8600獲得存儲總量
StorageFs8600Total("1.3.6.1.4.1.674.11000.2000.200.1.38.1","FS8600獲得存儲總量(單位MB)","get"),
//FS8600獲得存儲使用量
StorageFs8600Used("1.3.6.1.4.1.674.11000.2000.200.1.38.3","FS8600獲得存儲使用量(單位MB)","get"),
//存儲總量
StorageClusterTotal("1.3.6.1.4.1.12124.1.3.1.0", "存儲總量(從磁盤集群獲取)","get"),
//存儲已使用量
StorageClusterUsed("1.3.6.1.4.1.12124.1.3.2.0", "存儲使用量(從磁盤集群獲取)","get");
private String oid;
private String describe;
private String type;
OidEnum(String oid, String describe, String type) {
this.oid = oid;
this.describe = describe;
this.type = type;
}
public String getOid() {
return oid;
}
public String getdDscribe() {
return describe;
}
}四、SNMPTRAP
SNMP Trap是SNMP的一部分,當(dāng)被監(jiān)控段出現(xiàn)特定事件,可能是性能問題,甚至是網(wǎng)絡(luò)設(shè)備接口宕掉等,代理端會給管理站發(fā)告警事件。通過告警事件,管理站可以通過定義好的方法來處理告警。 trap是主動把告警信息推送到一個監(jiān)聽了162端口的接收程序,接收程序接收到的告警是一個OID,我們需要對oid進(jìn)行翻譯成可讀的告警信息,通過該OID去mib文件找到具體告警的詳情描述。 比較難的是解析MIB文件,我寫了個程序解析mib文件,發(fā)現(xiàn)有些文件解析不成功,也不知道為啥,去外網(wǎng)查了下,說是需要引入其他依賴的mib文件,不過我試了很多次還是不行。
1、接收程序代碼
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.CommunityTarget;
import org.snmp4j.MessageDispatcher;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.MessageException;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.log.LogFactory;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.StateReference;
import org.snmp4j.mp.StatusInformation;
import org.snmp4j.security.Priv3DES;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.smi.*;
import org.snmp4j.tools.console.SnmpRequest;
import org.snmp4j.transport.AbstractTransportMapping;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
@Slf4j
public class TrapReceiver implements CommandResponder {
public TrapReceiver() {
}
public static void main(String[] args) {
TrapReceiver snmp4jTrapReceiver = new TrapReceiver();
try {
snmp4jTrapReceiver.listen(new UdpAddress("10.11.26.219/162"));
} catch (IOException e) {
System.err.println("Error in Listening for Trap");
System.err.println("Exception Message = " + e.getMessage());
}
}
/**
* This method will listen for traps and response pdu's from SNMP agent.
*/
public synchronized void listen(TransportIpAddress address) throws IOException {
AbstractTransportMapping transport;
if (address instanceof TcpAddress) {
transport = new DefaultTcpTransportMapping((TcpAddress) address);
} else {
transport = new DefaultUdpTransportMapping((UdpAddress) address);
}
ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
// add message processing models
mtDispatcher.addMessageProcessingModel(new MPv1());
mtDispatcher.addMessageProcessingModel(new MPv2c());
// add all security protocols
SecurityProtocols.getInstance().addDefaultProtocols();
SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());
// Create Target
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("1q2w#E$R5t"));
Snmp snmp = new Snmp(mtDispatcher, transport);
snmp.addCommandResponder(this);
transport.listen();
System.out.println("Listening on " + address);
try {
this.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
/**
* This method will be called whenever a pdu is received on the given port
* specified in the listen() method
*/
public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {
log.debug("Received PDU...");
PDU pdu = cmdRespEvent.getPDU();
System.out.println(cmdRespEvent.toString());
System.out.println("接收到的trap信息:[發(fā)送來源="+cmdRespEvent.getPeerAddress()+",snmp版本="+"2"+",團(tuán)體名="+"public"+", 攜帶的變量="+cmdRespEvent.getPDU().getVariableBindings()+"]");
if (pdu != null) {
for (int i = 0; i < pdu.size(); i++) {
VariableBinding vb1 = pdu.get(i);
// System.err.println(vb1.toString());
}
int pduType = pdu.getType();
if ((pduType != PDU.TRAP) && (pduType != PDU.V1TRAP) && (pduType != PDU.REPORT)
&& (pduType != PDU.RESPONSE)) {
pdu.setErrorIndex(0);
pdu.setErrorStatus(0);
pdu.setType(PDU.RESPONSE);
StatusInformation statusInformation = new StatusInformation();
StateReference ref = cmdRespEvent.getStateReference();
try {
cmdRespEvent.getMessageDispatcher().returnResponsePdu(cmdRespEvent.getMessageProcessingModel(),
cmdRespEvent.getSecurityModel(), cmdRespEvent.getSecurityName(),
cmdRespEvent.getSecurityLevel(),
pdu, cmdRespEvent.getMaxSizeResponsePDU(), ref, statusInformation);
} catch (MessageException ex) {
System.err.println("Error while sending response: " + ex.getMessage());
LogFactory.getLogger(SnmpRequest.class).error(ex);
}
}
}
}
}2、解析mib文件說明
引入java的兩個jar包,mibble-2.9.3.jar和mibble-mibs-2.9.3.jar,我解析時,遇到有的文件解析成功,有的解析報(bào)錯。沒有解析成功的,可用用笨方法,就是用mib瀏覽器查看oid,把所有的告警OID做成一個字典。 因沒有實(shí)現(xiàn)成功,具體解析代碼我就不貼了。
到此這篇關(guān)于java通過snmp協(xié)議獲取物理設(shè)備信息的文章就介紹到這了,更多相關(guān)java的snmp協(xié)議獲取信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot集成quartz實(shí)現(xiàn)定時任務(wù)
這篇文章主要介紹了如何使用SpringBoot整合Quartz,并將定時任務(wù)寫入庫中(持久化存儲),還可以任意對定時任務(wù)進(jìn)行如刪除、暫停、恢復(fù)等操作,需要的可以了解下2023-09-09
IDEA 自帶的數(shù)據(jù)庫工具真的很牛(收藏版)
這篇文章主要介紹了IDEA 自帶的數(shù)據(jù)庫工具真的很牛(收藏版),本文以 IntelliJ IDEA/ Mac 版本作為演示,其他版本的應(yīng)該也差距不大,需要的朋友可以參考下2021-04-04
JAXB命名空間_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了JAXB命名空間的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Java傳入用戶名和密碼并自動提交表單實(shí)現(xiàn)登錄到其他系統(tǒng)的實(shí)例代碼
這篇文章主要介紹了Java傳入用戶名和密碼并自動提交表單實(shí)現(xiàn)登錄到其他系統(tǒng),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-01-01
SpringBoot集成FTP文件服務(wù)器簡單應(yīng)用方式
這篇文章主要介紹了SpringBoot集成FTP文件服務(wù)器簡單應(yīng)用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
擴(kuò)展tk.mybatis的流式查詢功能實(shí)現(xiàn)
mybatis查詢默認(rèn)是一次獲取全部,如果數(shù)據(jù)過于龐大,就會導(dǎo)致OOM問題,本文就介紹了tk.mybatis 流式查詢,具有一定的參考價值,感興趣的可以了解一下2021-12-12
java中LinkedBlockingQueue與ArrayBlockingQueue的異同
這篇文章主要介紹了java中LinkedBlockingQueue與ArrayBlockingQueue的異同,需要的朋友可以參考下2016-08-08

