java利用snmp4j包來讀取snmp協議資料(Manager端)
1 snmp簡單介紹
java利用snmp4j包來讀取snmp協議資料,很簡單的一個流程,就是利用java來讀取執行snmp協議的資料,例如伺服器、PC機或者路由器等運行了snmp協議的裝置。
snmp協議是什麼呢?
簡單網路管理協議(SNMP),由一組網路管理的標準組成,包含一個 應用層 協議(application layer protocol)、 資料庫模型 (database schema)和一組資源物件。該協議能夠支援 網路管理系統 ,用以監測連線到網路上的裝置是否有任何引起管理上關注的情況。該協議是網際網路工程工作小組(IETF,Internet Engineering TaskForce)定義的internet協議簇的一部分。SNMP的目標是管理 網際網路 Internet上眾多廠家生產的軟硬體平臺,因此SNMP受Internet標準 網路管理 框架的影響也很大。SNMP已經出到第三個版本的協議,其功能較以前已經大大地加強和改進了。
上面是百度百科上對於snmp的一個定義,其實很簡單,就是用來管理網路、檢視網路資訊的一種協議。
2 在本機上開啟snmp協議
那麼如何在本機上開啟snmp協議呢?
首先,在控制面板中找到“解除安裝程式”;
在彈出的視窗中單擊“開啟或關閉Windows功能”;
勾選彈出視窗中的“簡單網路管理協議(SNMP)”項後單擊“確定”並根據提示完成安裝即可。
完成SNMP服務的安裝後,右鍵單擊“計算機”選擇“管理”
在彈出的“計算機管理”視窗中左側導航欄中找到“服務”,並在右側找到“SNMPService”項;
滑鼠雙擊“SNMPService”選項,在彈出的視窗中切換到“安全”選項卡中,如下圖新增“接受的社群名稱”和接收那些主機發出的SNMP資料包。
“接受的社群名稱”是自己定義的任意字元都可以,接收那些主機發出的SNMP資料包定義成你的Nagios伺服器即可。到這裡被監控端的Windows主機的SNMP服務就配置完成了。
其中要注意的地方就是,在開啟後,還要到服務裡面給snmp協議新增public許可權。
3 snmp4j.jar包的下載
4 編碼測試
SnmpData:
package com.test.snmp; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.TransportMapping; import org.snmp4j.event.ResponseEvent; import org.snmp4j.event.ResponseListener; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.Address; import org.snmp4j.smi.GenericAddress; import org.snmp4j.smi.Integer32; import org.snmp4j.smi.Null; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; public class SnmpData { public static final int DEFAULT_VERSION = SnmpConstants.version2c; public static final String DEFAULT_PROTOCOL = "udp"; public static final int DEFAULT_PORT = 161; public static final long DEFAULT_TIMEOUT = 3 * 1000L; public static final int DEFAULT_RETRY = 3; /** * 建立物件communityTarget,用於返回target * * @param targetAddress * @param community * @param version * @param timeOut * @param retry * @return CommunityTarget */ public static CommunityTarget createDefault(String ip, String community) { Address address = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + ip + "/" + DEFAULT_PORT); CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(community)); target.setAddress(address); target.setVersion(DEFAULT_VERSION); target.setTimeout(DEFAULT_TIMEOUT); // milliseconds target.setRetries(DEFAULT_RETRY); return target; } /*根據OID,獲取單條訊息*/ public static void snmpGet(String ip, String community, String oid) { CommunityTarget target = createDefault(ip, community); Snmp snmp = null; try { PDU pdu = new PDU(); // pdu.add(new VariableBinding(new OID(new int[] // {1,3,6,1,2,1,1,2}))); pdu.add(new VariableBinding(new OID(oid))); DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); snmp.listen(); System.out.println("-------> 傳送PDU <-------"); pdu.setType(PDU.GET); ResponseEvent respEvent = snmp.send(pdu, target); System.out.println("PeerAddress:" + respEvent.getPeerAddress()); PDU response = respEvent.getResponse(); if (response == null) { System.out.println("response is null, request time out"); } else { // Vector<VariableBinding> vbVect = // response.getVariableBindings(); // System.out.println("vb size:" + vbVect.size()); // if (vbVect.size() == 0) { // System.out.println("response vb size is 0 "); // } else { // VariableBinding vb = vbVect.firstElement(); // System.out.println(vb.getOid() + " = " + vb.getVariable()); // } System.out.println("response pdu size is " + response.size()); for (int i = 0; i < response.size(); i++) { VariableBinding vb = response.get(i); System.out.println(vb.getOid() + " = " + vb.getVariable()); } } System.out.println("SNMP GET one OID value finished !"); } catch (Exception e) { e.printStackTrace(); System.out.println("SNMP Get Exception:" + e); } finally { if (snmp != null) { try { snmp.close(); } catch (IOException ex1) { snmp = null; } } } } /*根據OID列表,一次獲取多條OID資料,並且以List形式返回*/ public static void snmpGetList(String ip, String community, List<String> oidList) { CommunityTarget target = createDefault(ip, community); Snmp snmp = null; try { PDU pdu = new PDU(); for(String oid:oidList) { pdu.add(new VariableBinding(new OID(oid))); } DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); snmp.listen(); System.out.println("-------> 傳送PDU <-------"); pdu.setType(PDU.GET); ResponseEvent respEvent = snmp.send(pdu, target); System.out.println("PeerAddress:" + respEvent.getPeerAddress()); PDU response = respEvent.getResponse(); if (response == null) { System.out.println("response is null, request time out"); } else { System.out.println("response pdu size is " + response.size()); for (int i = 0; i < response.size(); i++) { VariableBinding vb = response.get(i); System.out.println(vb.getOid() + " = " + vb.getVariable()); } } System.out.println("SNMP GET one OID value finished !"); } catch (Exception e) { e.printStackTrace(); System.out.println("SNMP Get Exception:" + e); } finally { if (snmp != null) { try { snmp.close(); } catch (IOException ex1) { snmp = null; } } } } /*根據OID列表,採用非同步方式一次獲取多條OID資料,並且以List形式返回*/ public static void snmpAsynGetList(String ip, String community,List<String> oidList) { CommunityTarget target = createDefault(ip, community); Snmp snmp = null; try { PDU pdu = new PDU(); for(String oid:oidList) { pdu.add(new VariableBinding(new OID(oid))); } DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); snmp.listen(); System.out.println("-------> 傳送PDU <-------"); pdu.setType(PDU.GET); ResponseEvent respEvent = snmp.send(pdu, target); System.out.println("PeerAddress:" + respEvent.getPeerAddress()); PDU response = respEvent.getResponse(); /*非同步獲取*/ final CountDownLatch latch = new CountDownLatch(1); ResponseListener listener = new ResponseListener() { public void onResponse(ResponseEvent event) { ((Snmp) event.getSource()).cancel(event.getRequest(), this); PDU response = event.getResponse(); PDU request = event.getRequest(); System.out.println("[request]:" + request); if (response == null) { System.out.println("[ERROR]: response is null"); } else if (response.getErrorStatus() != 0) { System.out.println("[ERROR]: response status" + response.getErrorStatus() + " Text:" + response.getErrorStatusText()); } else { System.out.println("Received response Success!"); for (int i = 0; i < response.size(); i++) { VariableBinding vb = response.get(i); System.out.println(vb.getOid() + " = " + vb.getVariable()); } System.out.println("SNMP Asyn GetList OID finished. "); latch.countDown(); } } }; pdu.setType(PDU.GET); snmp.send(pdu, target, null, listener); System.out.println("asyn send pdu wait for response..."); boolean wait = latch.await(30, TimeUnit.SECONDS); System.out.println("latch.await =:" + wait); snmp.close(); System.out.println("SNMP GET one OID value finished !"); } catch (Exception e) { e.printStackTrace(); System.out.println("SNMP Get Exception:" + e); } finally { if (snmp != null) { try { snmp.close(); } catch (IOException ex1) { snmp = null; } } } } /*根據targetOID,獲取樹形資料*/ public static void snmpWalk(String ip, String community, String targetOid) { CommunityTarget target = createDefault(ip, community); TransportMapping transport = null; Snmp snmp = null; try { transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); transport.listen(); PDU pdu = new PDU(); OID targetOID = new OID(targetOid); pdu.add(new VariableBinding(targetOID)); boolean finished = false; System.out.println("----> demo start <----"); while (!finished) { VariableBinding vb = null; ResponseEvent respEvent = snmp.getNext(pdu, target); PDU response = respEvent.getResponse(); if (null == response) { System.out.println("responsePDU == null"); finished = true; break; } else { vb = response.get(0); } // check finish finished = checkWalkFinished(targetOID, pdu, vb); if (!finished) { System.out.println("==== walk each vlaue :"); System.out.println(vb.getOid() + " = " + vb.getVariable()); // Set up the variable binding for the next entry. pdu.setRequestID(new Integer32(0)); pdu.set(0, vb); } else { System.out.println("SNMP walk OID has finished."); snmp.close(); } } System.out.println("----> demo end <----"); } catch (Exception e) { e.printStackTrace(); System.out.println("SNMP walk Exception: " + e); } finally { if (snmp != null) { try { snmp.close(); } catch (IOException ex1) { snmp = null; } } } } private static boolean checkWalkFinished(OID targetOID, PDU pdu, VariableBinding vb) { boolean finished = false; if (pdu.getErrorStatus() != 0) { System.out.println("[true] responsePDU.getErrorStatus() != 0 "); System.out.println(pdu.getErrorStatusText()); finished = true; } else if (vb.getOid() == null) { System.out.println("[true] vb.getOid() == null"); finished = true; } else if (vb.getOid().size() < targetOID.size()) { System.out.println("[true] vb.getOid().size() < targetOID.size()"); finished = true; } else if (targetOID.leftMostCompare(targetOID.size(), vb.getOid()) != 0) { System.out.println("[true] targetOID.leftMostCompare() != 0"); finished = true; } else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) { System.out .println("[true] Null.isExceptionSyntax(vb.getVariable().getSyntax())"); finished = true; } else if (vb.getOid().compareTo(targetOID) <= 0) { System.out.println("[true] Variable received is not " + "lexicographic successor of requested " + "one:"); System.out.println(vb.toString() + " <= " + targetOID); finished = true; } return finished; } /*根據targetOID,非同步獲取樹形資料*/ public static void snmpAsynWalk(String ip, String community, String oid) { final CommunityTarget target = createDefault(ip, community); Snmp snmp = null; try { System.out.println("----> demo start <----"); DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); snmp.listen(); final PDU pdu = new PDU(); final OID targetOID = new OID(oid); final CountDownLatch latch = new CountDownLatch(1); pdu.add(new VariableBinding(targetOID)); ResponseListener listener = new ResponseListener() { public void onResponse(ResponseEvent event) { ((Snmp) event.getSource()).cancel(event.getRequest(), this); try { PDU response = event.getResponse(); // PDU request = event.getRequest(); // System.out.println("[request]:" + request); if (response == null) { System.out.println("[ERROR]: response is null"); } else if (response.getErrorStatus() != 0) { System.out.println("[ERROR]: response status" + response.getErrorStatus() + " Text:" + response.getErrorStatusText()); } else { System.out .println("Received Walk response value :"); VariableBinding vb = response.get(0); boolean finished = checkWalkFinished(targetOID, pdu, vb); if (!finished) { System.out.println(vb.getOid() + " = " + vb.getVariable()); pdu.setRequestID(new Integer32(0)); pdu.set(0, vb); ((Snmp) event.getSource()).getNext(pdu, target, null, this); } else { System.out .println("SNMP Asyn walk OID value success !"); latch.countDown(); } } } catch (Exception e) { e.printStackTrace(); latch.countDown(); } } }; snmp.getNext(pdu, target, null, listener); System.out.println("pdu 已傳送,等到非同步處理結果..."); boolean wait = latch.await(30, TimeUnit.SECONDS); System.out.println("latch.await =:" + wait); snmp.close(); System.out.println("----> demo end <----"); } catch (Exception e) { e.printStackTrace(); System.out.println("SNMP Asyn Walk Exception:" + e); } } /*根據OID和指定string來設定裝置的資料*/ public static void setPDU(String ip,String community,String oid,String val) throws IOException { CommunityTarget target = createDefault(ip, community); Snmp snmp = null; PDU pdu = new PDU(); pdu.add(new VariableBinding(new OID(oid),new OctetString(val))); pdu.setType(PDU.SET); DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping(); snmp = new Snmp(transport); snmp.listen(); System.out.println("-------> 傳送PDU <-------"); snmp.send(pdu, target); snmp.close(); } }
SnmpTest:
package com.test.snmp;
import java.util.ArrayList;
import java.util.List;
import org.snmp4j.log.ConsoleLogFactory;
import org.snmp4j.log.LogAdapter;
import org.snmp4j.log.LogFactory;
import com.test.snmp.SnmpData;
public class SnmpTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
SnmpTest test = new SnmpTest();
test.testGet();
}
public void testGet()
{
String ip = "127.0.0.1";
String community = "public";
String oidval = "1.3.6.1.2.1.1.6.0";
SnmpData.snmpGet(ip, community, oidval);
}
public void testGetList(){
String ip = "127.0.0.1";
String community = "public";
List<String> oidList=new ArrayList<String>();
oidList.add("1.3.6.1.2.1.1.5.0");
oidList.add("1.3.6.1.2.1.1.7.0");
SnmpData.snmpGetList(ip, community, oidList);
}
public void testGetAsyList()
{
String ip = "127.0.0.1";
String community = "public";
List<String> oidList=new ArrayList<String>();
oidList.add("1.3.6.1.2.1");
oidList.add("1.3.6.1.2.12");
SnmpData.snmpAsynGetList(ip, community, oidList);
System.out.println("i am first!");
}
public void testWalk()
{
String ip = "127.0.0.1";
String community = "public";
String targetOid = "1.3.6.1.2.1.1.5.0";
SnmpData.snmpWalk(ip, community, targetOid);
}
public void testAsyWalk()
{
String ip = "127.0.0.1";
String community = "public";
// 非同步採集資料
SnmpData.snmpAsynWalk(ip, community, "1.3.6.1.2.1.25.4.2.1.2");
}
public void testSetPDU() throws Exception
{
String ip = "127.0.0.1";
String community = "public";
SnmpData.setPDU(ip, community, "1.3.6.1.2.1.1.6.0","jianghuiwen");
}
public void testVersion()
{
System.out.println(org.snmp4j.version.VersionInfo.getVersion());
}
}
-------------------------更新--------------------------------------
Trap功能的實現:
下面是兩個用於傳送和接收Trap報文資訊的類:
接收Trap訊息類:
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Vector;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
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.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
/**
* 本類用於監聽代理程序的Trap資訊
*
* @author zhanjia
*
*/
public class MultiThreadedTrapReceiver implements CommandResponder {
private MultiThreadedMessageDispatcher dispatcher;
private Snmp snmp = null;
private Address listenAddress;
private ThreadPool threadPool;
public MultiThreadedTrapReceiver() {
// BasicConfigurator.configure();
}
private void init() throws UnknownHostException, IOException {
threadPool = ThreadPool.create("Trap", 2);
dispatcher = new MultiThreadedMessageDispatcher(threadPool,
new MessageDispatcherImpl());
listenAddress = GenericAddress.parse(System.getProperty(
"snmp4j.listenAddress", "udp:192.168.1.23/162")); // 本地IP與監聽埠
TransportMapping transport;
// 對TCP與UDP協議進行處理
if (listenAddress instanceof UdpAddress) {
transport = new DefaultUdpTransportMapping(
(UdpAddress) listenAddress);
} else {
transport = new DefaultTcpTransportMapping(
(TcpAddress) listenAddress);
}
snmp = new Snmp(dispatcher, transport);
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3
.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
snmp.listen();
}
public void run() {
try {
init();
snmp.addCommandResponder(this);
System.out.println("開始監聽Trap資訊!");
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 實現CommandResponder的processPdu方法, 用於處理傳入的請求、PDU等資訊
* 當接收到trap時,會自動進入這個方法
*
* @param respEvnt
*/
public void processPdu(CommandResponderEvent respEvnt) {
// 解析Response
if (respEvnt != null && respEvnt.getPDU() != null) {
Vector<VariableBinding> recVBs = respEvnt.getPDU().getVariableBindings();
for (int i = 0; i < recVBs.size(); i++) {
VariableBinding recVB = recVBs.elementAt(i);
System.out.println(recVB.getOid() + " : " + recVB.getVariable());
}
}
}
public static void main(String[] args) {
MultiThreadedTrapReceiver multithreadedtrapreceiver = new MultiThreadedTrapReceiver();
multithreadedtrapreceiver.run();
}
}
傳送Trap訊息的類:
import java.io.IOException;
import java.util.Vector;
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;
/**
* 本類用於向管理程序傳送Trap資訊
*
* @author zhanjia
*
*/
public class SnmpUtilSendTrap {
private Snmp snmp = null;
private Address targetAddress = null;
public void initComm() throws IOException {
// 設定管理程序的IP和埠
targetAddress = GenericAddress.parse("udp:192.168.1.23/162");
TransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
transport.listen();
}
/**
* 向管理程序傳送Trap報文
*
* @throws IOException
*/
public void sendPDU() throws IOException {
// 設定 target
CommunityTarget target = new CommunityTarget();
target.setAddress(targetAddress);
// 通訊不成功時的重試次數
target.setRetries(2);
// 超時時間
target.setTimeout(1500);
// snmp版本
target.setVersion(SnmpConstants.version2c);
// 建立 PDU
PDU pdu = new PDU();
pdu.add(new VariableBinding(new OID(".1.3.6.1.2.3377.10.1.1.1.1"),
new OctetString("SnmpTrap")));
pdu.add(new VariableBinding(new OID(".1.3.6.1.2.3377.10.1.1.1.2"),
new OctetString("JavaEE")));
pdu.setType(PDU.TRAP);
// 向Agent傳送PDU,並接收Response
ResponseEvent respEvnt = snmp.send(pdu, target);
// 解析Response
if (respEvnt != null && respEvnt.getResponse() != null) {
Vector<VariableBinding> recVBs = respEvnt.getResponse()
.getVariableBindings();
for (int i = 0; i < recVBs.size(); i++) {
VariableBinding recVB = recVBs.elementAt(i);
System.out.println(recVB.getOid() + " : " + recVB.getVariable());
}
}
}
public static void main(String[] args) {
try {
SnmpUtilSendTrap util = new SnmpUtilSendTrap();
util.initComm();
util.sendPDU();
} catch (IOException e) {
e.printStackTrace();
}
}
}
1、執行MultiThreadedTrapReceiver類,提示“開始監聽Trap資訊!”並處理監聽狀態
2、執行SnmpUtilSendTrap類,執行完畢後,將會在“開始監聽Trap資訊!”後面顯示:
1.3.6.1.2.3377.10.1.1.1.1 : SnmpTrap
1.3.6.1.2.3377.10.1.1.1.2 : JavaEE
MultiThreadedTrapReceiver輸出面板中顯示以上兩行即表示測試成功!
說明:
本例只在本人電腦上測試過,作業系統為Windows
ref:http://www.iteye.com/topic/308836-----------------------------------------------------更新20160621-------------------------------------------------