Java發(fā)送SNMP至交換機(jī)獲取交換機(jī)狀態(tài)實(shí)現(xiàn)方式
交換機(jī)協(xié)議
這里使用的交換機(jī)協(xié)議為常見的RCF1213-MIB協(xié)議,使用SNMP協(xié)議與交換機(jī)進(jìn)行通信。前提記得開啟交換機(jī)對(duì)于SNMP協(xié)議的支持
SNMP庫(kù)
使用SNMP4J庫(kù)進(jìn)行開發(fā),maven提供了相應(yīng)的pom,筆者使用的版本為2.7.0。pom內(nèi)容如下
<!-- snmp4j依賴包 -->
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.7.0</version>
</dependency>
獲取交換機(jī)單路狀態(tài)
首先明確交換機(jī)所在的IP地址,交換機(jī)提供的公共團(tuán)體名稱以及對(duì)應(yīng)的OID
團(tuán)體名稱簡(jiǎn)單的來說就是驗(yàn)證碼
如果 A 要訪問B 的核心內(nèi)容A 必須有B 的公鑰,在和B 通信的時(shí)候B 也必須能認(rèn)證A 持有的公鑰
這個(gè)過程中的公鑰和SNMP的團(tuán)體名稱功能類似
- OID(對(duì)象標(biāo)識(shí)符),是SNMP代理提供的具有唯一標(biāo)識(shí)的鍵值。
- OID看起來和一個(gè)IPv6的地址很像,并且不同的廠商有不同的前綴等信息。具體可以在協(xié)議文件中查看。公開的協(xié)議OID也可在網(wǎng)絡(luò)上查詢到。
// 配置交換機(jī)的SNMP參數(shù)
// 交換機(jī)的IP地址
String ipAddress = "192.168.1.1";
// 公共團(tuán)體名稱
String community = "public";
// RFC1213-MIB中的ifOperStatus OID,用于獲取接口的操作狀態(tài)
String oidValue = "1.3.6.1.2.1.2.2.1.8";
第二步設(shè)定好目標(biāo)地址以及基礎(chǔ)的超時(shí)重試信息
其中SNMP協(xié)議一共有三個(gè)版本,第一代能力欠缺,第三代還處于測(cè)試階段,因此使用能力較為豐富且穩(wěn)定的第二代SNMP協(xié)議。
- SNMPv1: SNMPv1是最早的SNMP版本,它提供最基本的網(wǎng)絡(luò)管理功能。它使用簡(jiǎn)單的社區(qū)字符串(community string)來進(jìn)行認(rèn)證,發(fā)送的消息以明文形式傳輸。SNMPv1具有較少的安全功能,并且易受到攻擊。
- SNMPv2: SNMPv2是對(duì)SNMPv1的改進(jìn)版本。它引入了擴(kuò)展的管理功能和更復(fù)雜的消息格式。SNMPv2分為SNMPv2c(community-basedSNMPv2)和SNMPv2u(user-basedSNMPv2)兩種形式。SNMPv2c仍然使用社區(qū)字符串進(jìn)行認(rèn)證,而SNMPv2u引入了更復(fù)雜的用戶認(rèn)證和訪問控制機(jī)制。然而,SNMPv2的安全性仍然有限,容易受到攻擊。
- SNMPv3: SNMPv3是最新和最安全的SNMP版本。它提供了更強(qiáng)大的安全性功能,如消息加密、用戶身份認(rèn)證和訪問控制。SNMPv3使用基于用戶的安全模型(USM)來提供安全性。用戶可以使用用戶名和密碼進(jìn)行身份認(rèn)證,并且可以使用加密機(jī)制對(duì)消息進(jìn)行保護(hù)。SNMPv3還引入了VACM(View-based Access Control Model)來管理對(duì)設(shè)備的訪問控制。
// 創(chuàng)建目標(biāo)地址。這里使用的是UDP協(xié)議,并指定了交換機(jī)的IP地址和SNMP端口161。
Address targetAddress = GenericAddress.parse("udp:" + ipAddress + "/161");
// 創(chuàng)建一個(gè)社區(qū)目標(biāo)對(duì)象,用于存儲(chǔ)SNMP的目標(biāo)信息。
CommunityTarget target = new CommunityTarget();
// 設(shè)置目標(biāo)的社區(qū)字符串。這里使用的是"public"。
target.setCommunity(new OctetString(community));
// 設(shè)置目標(biāo)的地址,即前面創(chuàng)建的目標(biāo)地址。
target.setAddress(targetAddress);
// 設(shè)置請(qǐng)求失敗時(shí)的重試次數(shù),這里設(shè)置為2次。
target.setRetries(2);
// 設(shè)置請(qǐng)求的超時(shí)時(shí)間,單位為毫秒,這里設(shè)置為1500毫秒(1.5秒)。
target.setTimeout(1500);
// 設(shè)置SNMP的版本,這里使用的是SNMP v2c。
target.setVersion(SnmpConstants.version2c);
第三步創(chuàng)建TransportMapping并監(jiān)聽SNMP的返回值
第三步主要通過PDU這個(gè)對(duì)象單元來進(jìn)行數(shù)據(jù)的交換。
一個(gè)PDU(Protocol Data Unit)對(duì)象,用于封裝SNMP請(qǐng)求。
try {
// 創(chuàng)建UDP傳輸映射,用于SNMP通信。
TransportMapping<?> transport = new DefaultUdpTransportMapping();
// 監(jiān)聽傳輸映射,即啟動(dòng)SNMP傳輸。
transport.listen();
// 創(chuàng)建一個(gè)Snmp對(duì)象,用于發(fā)送和接收SNMP消息
Snmp snmp = new Snmp(transport);
// 創(chuàng)建PDU
PDU pdu = new PDU();
// 創(chuàng)建一個(gè)PDU(Protocol Data Unit)對(duì)象,用于封裝SNMP請(qǐng)求。
pdu.add(new VariableBinding(new OID(oidValue)));
// 設(shè)置PDU的類型為GETNEXT,用于獲取單個(gè)變量。
pdu.setType(PDU.GETNEXT);
// 發(fā)送請(qǐng)求
boolean finished = false;
while (!finished) {
// 發(fā)送SNMP請(qǐng)求,并接收響應(yīng)事件。
ResponseEvent responseEvent = snmp.send(pdu, target);
// 獲取響應(yīng)PDU。
PDU responsePDU = responseEvent.getResponse();
.............
.............
}
snmp.close();
// 關(guān)閉SNMP對(duì)象,釋放資源。
} catch (Exception e) {
e.printStackTrace();
// 捕獲并打印異常。
}
第四步處理我們請(qǐng)求的返回值
if (responsePDU != null) {
for (VariableBinding vb : responsePDU.getVariableBindings()) {
// 檢查響應(yīng)中的OID是否屬于請(qǐng)求的OID范圍。
if (vb.getOid().toString().startsWith(oidValue)) {
// 打印OID及其對(duì)應(yīng)的變量值。
System.out.println(vb.getOid() + " = " + vb.getVariable());
// 重置請(qǐng)求ID。
pdu.setRequestID(new Integer32(0));
// 將PDU的第一個(gè)變量設(shè)置為上次收到的OID,以獲取下一個(gè)變量。
pdu.set(0, vb);
} else {
// 如果OID不再屬于請(qǐng)求的范圍,則完成循環(huán)。
finished = true;
break;
}
}
} else {
finished = true;
// 如果響應(yīng)PDU為空,則完成循環(huán)。
}
完整代碼如下
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;
public class SnmpGet {
public static void main(String[] args) {
// 配置交換機(jī)的SNMP參數(shù)
// 交換機(jī)的IP地址
String ipAddress = "192.168.1.1";
// 公共團(tuán)體名稱
String community = "public";
// RFC1213-MIB中的ifOperStatus OID,用于獲取接口的操作狀態(tài)
String oidValue = "1.3.6.1.2.1.2.2.1.8";
// 創(chuàng)建目標(biāo)
Address targetAddress = GenericAddress.parse("udp:" + ipAddress + "/161");
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString(community));
target.setAddress(targetAddress);
target.setRetries(2);
target.setTimeout(1500);
target.setVersion(SnmpConstants.version2c);
// 創(chuàng)建TransportMapping并監(jiān)聽
try {
TransportMapping<?> transport = new DefaultUdpTransportMapping();
transport.listen();
Snmp snmp = new Snmp(transport);
// 創(chuàng)建PDU
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(oidValue)));
pdu.setType(PDU.GETNEXT);
// 發(fā)送請(qǐng)求
ResponseEvent responseEvent = snmp.send(pdu, target);
PDU responsePDU = responseEvent.getResponse();
if (responsePDU != null) {
for (VariableBinding vb : responsePDU.getVariableBindings()) {
System.out.println(vb.getOid() + " = " + vb.getVariable());
}
} else {
System.out.println("響應(yīng)PDU為空");
}
snmp.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
獲取交換機(jī)多路狀態(tài)
關(guān)鍵點(diǎn)就在于修改PDU的屬性設(shè)置,其他同單路一樣。
SNMP的GETBULK操作來獲取多個(gè)結(jié)果,可以提高獲取大量信息的效率。
pdu.setType(PDU.GETBULK); // 每次請(qǐng)求的最大重復(fù)次數(shù) pdu.setMaxRepetitions(10); // 非重復(fù)計(jì)數(shù)器 pdu.setNonRepeaters(0);
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用spring gateway微服務(wù)網(wǎng)關(guān)(基本用法)
本文介紹spring gateway的使用,包括配置文件的使用和調(diào)試跟蹤,讓大家了解spring gateway的基本用法,感興趣的朋友跟隨小編一起看看吧2024-08-08
SpringBoot讀取yml文件中配置數(shù)組的2種方法
這篇文章主要介紹了SpringBoot讀取yml文件中配置數(shù)組的2種方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(4)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07
java求最大公約數(shù)與最小公倍數(shù)的方法示例
這篇文章主要介紹了java求最大公約數(shù)與最小公倍數(shù)的方法,涉及java數(shù)值運(yùn)算的相關(guān)操作技巧,并附帶分析了eclipse環(huán)境下設(shè)置運(yùn)行輸入?yún)?shù)的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
MyBatis傳入?yún)?shù)的實(shí)例代碼
這篇文章主要介紹了MyBatis傳入?yún)?shù)的實(shí)例代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
詳解eclipse將項(xiàng)目打包成jar文件的兩種方法及問題解決方法
本文給大家介紹了eclipse中將項(xiàng)目打包成jar文件的兩種方法及其遇到問題解決方法,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下2017-12-12

