SNMP4J教程

一、SNMP簡介
 
SNMP指的是簡單網絡管理協議。它屬於TCP/IP五層協議中的應用層協議。它提供了一種簡單和方便的模式來管理網絡中的各個元素。這裏的元素就是各個被管理的對象,可以是因特網中的某個硬件,比如網卡,也可以是某些硬件和軟件的配置參數的集合。由於SNMP協議簡單可靠 ,受到了衆多廠商的歡迎,成爲了目前最爲廣泛的網管協議。
 
SNMP協議主要由兩大部分構成:SNMP管理站和SNMP代理。SNMP管理站是一箇中心節點,負責收集維護各個SNMP元素的信息,並對這些信息進行處理,最後反饋給網絡管理員;而SNMP代理是運行在各個被管理的網絡節點之上,負責統計該節點的各項信息,並且負責與SNMP管理站交互,接收並執行管理站的命令,上傳各種本地的網絡信息。
 
SNMP管理站和SNMP代理之間是鬆散耦合。他們之間的通信是通過UDP協議完成的。一般情況下,SNMP管理站通過UDP協議向SNMP代理髮送各種命令,當SNMP代理收到命令後,返回SNMP管理站需要的參數。但是當SNMP代理檢測到網絡元素異常的時候,也可以主動向SNMP管理站發送消息,通告當前異常狀況。
 
SNMP協議於1988年發佈。到目前一共經歷了V1,V2,V3三個版本。其中V1已經被廢棄,而V2c雖然沒有能夠成爲正式標準,,但是已經被很多廠家所接受,V3目前是因特網的正式標準。與V1相比,V2,V3更能適應大規模的網絡管理,而且在安全方面有了較大的改進。
 
二、SNMP4J詳細介紹
 
2.1 重要的類和接口
 
Snmp類:該類是SNMP4J中最爲核心的類。負責SNMP報文的接受和發送。
 
PDU類和ScopedPDU類:該類是SNMP報文單元的抽象,其中PDU類適用於SNMPv1和SNMPv2c。ScopedPDU類繼承於PDU類,適用於SNMPv3。
 
Target接口和UserTarget類:對應於SNMP代理的地址信息,包括IP地址和端口號(161)。其中Target接口適用於SNMPv1和SNMPv2c。UserTarget類實現了Target接口,適用於SNMPv3。
 
TransportMapping接口:該接口代表了SNMP4J所使用的傳輸層協議。這也是SNMP4J一大特色的地方。按照RFC的規定,SNMP是隻使用UDP作爲傳輸層協議的。而SNMP4J支持管理端和代理端使用UDP或者TCP進行傳輸。該接口有兩個子接口。
 
2.2 兩種消息發送模式
 
SNMP4J支持兩種消息發送模式:同步發送模式和異步發送模式。
 
其中同步發送模式也稱阻塞模式。當管理端發送出一條消息之後,線程會被阻塞,直到收到對方的迴應或者時間超時。同步發送模式編程較爲簡單,但是不適用於發送廣播消息。
 
異步發送模式也稱非阻塞模式。當程序發送一條消息之後,線程將會繼續執行,當收到消息的迴應的時候,程序會對消息作出相應的處理。要實現異步發送模式,需要實例化一個實現了ResponseListener接口的類的對象。ResponseListener接口中有一個名爲onResponse的函數。這是一個回調函數,當程序收到響應的時候,會自動調用該函數。由該函數完成對響應的處理。
 
2.3 實現管理端的總體步驟
 
該部分說明了利用SNMP4J編寫SNMP管理端的大致過程,讀者在閱讀之後會對SNMP4J有一個宏觀上的認識。在附錄部分,作者給出了一個用SNMP4J開發管理站的樣例程序,如果有進一步的需要,請參考附錄部分。
 
2.3.1 初始化
 
l  明確SNMP在傳輸層所使用的協議
 
一般情況下,我們都使用使用UDP協議作爲SNMP的傳輸層協議,所以我們需要實例化的是一個DefaultUdpTransportMapping接口對象;
 
l  實例化一個snmp對象
 
在此過程中,我們需要將1中實例化的DefaultUdpTransportMapping接口的對象作爲參數,穿snmp類的構造函數中。
 
另外,如果實現的SNMPv3協議,我們還需要設置安全機制,添加安全用戶等等;
 
l  監聽snmp消息
 
在此,我們可以調用剛剛實例化的DefaultUdpTransportMapping的接口對象的listen方法,讓程序監聽snmp消息;
 
2.3.2 構造發送目標
 
如果實現的是SNMPv3程序,則需要實例化一個UserTarget對象,如果實現的是SNMPv2c或者說SNMPv1,則需要實例化一個CommunityTarget對象。
 
之後,我們還需要對實例化的對象做一些設置。如果是CommunityTarget的對象,則需要設置版本,重傳時間和等待時延。如果是UserTarget對象,我們不僅需要設置版本、重傳時間、等待時延,還需要設置安全級別和安全名稱。
 
2.3.3 構造發送報文
 
如果發送的是SNMPv3的報文,我們則需要實例化一個ScopedPDU       類的對象,否則我們需要實例化一個PDU類的對象。之後,我們還需要生成一個OID對象,其中包含了我們所需要獲取的SNMP對象在MIB庫中的ID。然後我們需要將OID和之前生成的PDU對象或者是ScopedPDU對象綁定,並且設置PDU的報文類型(五種SNMP報文類型之一)。
 
2.3.4 構造響應監聽對象(異步模式)
 
當使用異步模式的時候,我們需要實例化一個實現了ResponseListener
 
的對象,作爲響應消息的監聽對象。在構造該對象的過程中,我們需要重寫ResponseListener的OnResponse函數,該函數是一個回調函數,用來處理程序收到響應後的一些操作。
 
2.3.5 發送消息
 
當所有上述操作都設置完畢之後,就可以發送消息了。同步模式和異步模式發送消息調用的函數名字均爲send,但是兩個函數所需參數不一樣。同步模式的參數僅爲4.3.2和4.3.3中構造的目標對象和報文對象,而異步模式還需要4.3.4中構造的監聽對象。
 
同步模式發送消息後便等待響應的到達,到達之後會返回一個ResponseEvent對象,該對象中包含了響應的相應信息。
 
異步模式發送消息之後便會繼續執行,當收到響應消息時便會調用監聽對象的OnResponse函數。該函數中的語句便是我們對響應的處理
 
三、例程
 


import java.io.IOException;
 
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
 
public class snmp_manager {
 private Snmp snmp = null;
 private String version=null;
 
 public snmp_manager(String version) {
  try {
   this.version=version;
   TransportMapping transport = new DefaultUdpTransportMapping();
   snmp = new Snmp(transport);
   if(version.equals("3"))
   {
    //設置安全模式
    USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(
      MPv3.createLocalEngineID()), 0);
    SecurityModels.getInstance().addSecurityModel(usm);
   }
   //開始監聽消息
   transport.listen();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 public void sendMessage(Boolean syn, final Boolean bro, PDU pdu,
   String addr) throws IOException {
  //生成目標地址對象
  Address targetAddress = GenericAddress.parse(addr);
  Target target=null;
  if(version.equals("3"))
  {
   //添加用戶
  snmp.getUSM().addUser(
    new OctetString("MD5DES"),
    new UsmUser(new OctetString("MD5DES"), AuthMD5.ID,
      new OctetString("MD5DESUserAuthPassword"), PrivDES.ID,
      new OctetString("MD5DESUserPrivPassword")));
 
  target = new UserTarget();
  //設置安全級別
  ((UserTarget)target).setSecurityLevel(SecurityLevel.AUTH_PRIV);
  ((UserTarget)target).setSecurityName(new OctetString("MD5DES"));
  target.setVersion(SnmpConstants.version3);
  }else{
   target=new CommunityTarget();
   if(version.equals("1"))
   {
    target.setVersion(SnmpConstants.version1);
    ((CommunityTarget) target).setCommunity(new OctetString("public"));
   }else{
    target.setVersion(SnmpConstants.version2c);
    ((CommunityTarget) target).setCommunity(new OctetString("public"));
   }
     
  }
  // 目標對象相關設置
  target.setAddress(targetAddress);
  target.setRetries(5);
  target.setTimeout(1000);
 
 
  if (syn.equals(true)) {
   //發送報文  並且接受響應
   ResponseEvent response = snmp.send(pdu, target);
   //處理響應
   System.out.println("Synchronize message from "
     + response.getPeerAddress() + "\nrequest:"
     + response.getRequest() + "\nresponse:"
     + response.getResponse());
  } else {
   //設置監聽對象
   ResponseListener listener = new ResponseListener() {
 
    @Override
    public void onResponse(ResponseEvent event) {
     // TODO Auto-generated method stub
     if (bro.equals(false)) {
      ((Snmp) event.getSource()).cancel(event.getRequest(),
        this);
     }
     //處理響應
     PDU request = event.getRequest();
     PDU response = event.getResponse();
     System.out.println("Asynchronise message from "
       + event.getPeerAddress() + "\nrequest:" + request
       + "\nresponse:" + response);
    }
 
   };
   //發送報文
   snmp.send(pdu, target, null, listener);
  }
 }
 
 public static void main(String[] args) {
  snmp_manager manager = new snmp_manager("2c");
  //構造報文
  PDU pdu = new PDU();
//  PDU pdu = new ScopedPDU();
  //設置要獲取的對象ID
  OID oids=new OID("1.3.6.1.2.1.1.1.0");
  pdu.add(new VariableBinding(oids));
  //設置報文類型
  pdu.setType(PDU.GETNEXT);
 //   ((ScopedPDU) pdu).setContextName(new OctetString("priv")); 
  try {
  //發送消息   其中最後一個是想要發送的目標地址
   manager.sendMessage(false, true, pdu, "udp:192.168.1.255/161");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/RiverM/archive/2011/03/01/6215028.aspx

發佈了5 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章