SMTP

자바를 이용한 SNMP 데이터 가져오기 - 4 - (소스코드 완성본)

bang2001 2013. 7. 25. 17:43

import org.opennms.protocols.snmp.*;

import org.opennms.protocols.snmp.asn1.*;

import java.lang.System;

import java.util.*;

import java.net.*;


/** 이 클래스를 테스트 하기 위해서는 SNMP Agent가 필요합니다. */

public class SNMPGet implements SnmpHandler {

private SnmpParameters params;

private SnmpSession session;


public SNMPGet(InetAddress address, String community) {

try {

// 읽기를 위한 SNMP 커뮤니티 이름에 대한 문자열 정보를 포함하는 SnmpParameters 인스턴스 생성

// SnmpParameters 클래스는 SnmpSession에서 SNMP에이전트와의 통신에 사용할 SNMP 버전정보 및

// 커뮤니티 이름(읽기, 쓰기)에

// 대한 정보를 담당하게 된다. SnmpParameters 클래스를 사용하여 이와같은 정보들을 설정한다.

this.params = new SnmpParameters(community);


// SnmpSession 생성 SnmpSession은 manager와 agent 사이에 통신을 하기위한

// 클래스이다.(통신담당)

/*

* 다음은 SnmpSession 클래스에 API 문서의 설명이다. The SnmpSession is the main

* connection between the SNMP manager and the SNMP Agent.

* (SnmpSession은 SNMP 매니저와 SNMP 에이전트 사이의 주된 연결입니다.) All the request

* flow through this class. (모든 요청은 이 클래스를 통해서 흐릅니다.) To use the

* SnmpSession class a SnmpHandler class must be defined to process

* any errors or responses through the library. (SnmpSession 클래스를

* 사용하려면 반드시 에러 혹은 응답 라이브러리를 통해 프로세스에 정의된 SnmpHandler 클래스를 사용해야

* 합니다.)

*/

this.session = new SnmpSession(address, params);


// SnmpSession의 기본 Handler 등록

this.session.setDefaultHandler(this);


// session에 이벤트 헨들러가 이 클래스임을 지정한다. 이 클래스는 SnmpHandler인터페이스를

// implements 하였다.

// 추후 핸들러를 따로 구현한 클래스로 등록하자.

} catch (Exception e) {

System.out.println("SnmpSession객체 생성중 예외발생");

e.printStackTrace();

}


}// 기본생성자()=======================================================================


/*

* 다음 하단의 오버라이드한 메소드는 SnmpHandler 인터페이스 상속에 따른 추상 메소드 들이다. 각 이벤트에 대한 메소드들인데,

* 보시다시피 이터널에러, 정상적인 데이터 수신, 무응답에 따른 타임아웃 에러가 있다.

*/

@Override

public void snmpInternalError(SnmpSession session, int err, SnmpSyntax pdu) {

System.out.println("인터널 에러 발생");


// 메시지를 받으면 대기상태에서 해지되도록 한다.

synchronized (session) {

session.notify();

}

}// snmpInternalError()================================================================


@Override

public void snmpReceivedPdu(SnmpSession session, int command,

SnmpPduPacket pdu) {

System.out.println("데이터를 받았습니다.");

SnmpVarBind vb[] = pdu.toVarBindArray();

String value = null;

for (int i = 0; i < vb.length; i++) {

SnmpSyntax snmpValue = vb[i].getValue();

switch (snmpValue.typeId()) {

/*

* ANS이란? 플렛폼에 상관없이 데이터를 기술하기 위한 언어. 즉, 서로다른 환경을 갖고 있는 장비에서 동일한 데이터를

* 인식하기 위해 사용되는 문법을 말한다. 다른 기종간에 같은 데이터를 다르게 표현할 수 있는데 이러한 데이터들을

* 교환하고 다른 장치들끼리 인식할 수 있도록 하기 위해 만들어졌다.

* ASN은 CCITT와 ISO의 공동표준. 응용프로그램 데이터를 추상적으로 정의하거나 응용프로그램의 구조를 정의, 주로

* PDU들을 정의하는데 사용. ASN은 문법이며, switch - case 문에서 사용한 ASN1은 openNMS 에서

* 정의한 클래스로 패키지는 org.opennms.protocols.snmp.asn1 패키지에 있다. ASN1 클래스에

* 대한 설명은 다음과 같다.

* Public ASN.1 definitions. See

* "SNMPv1, SNMPv2, SNMPv3 and RMON 1 and 2, 3rd Ed." by William

* Stallings, Published by Addision Wesley for more information.

* (Public ASN.1은 정의. William Stallings(사람이름) 의한

* "SNMPv1, SNMPv2, SNMPv3 and RMON 1 and 2, 3rd Ed." 와 Addision

* Wesley가 발행한 정보를 참조하십시오.)

*/

case ASN1.OCTETSTRING: // static 맴버변수

value = new String(((SnmpOctetString) snmpValue).getString()); // 리턴하여

// 받은값을

// 문자열로

// 출력하기

// 위한

// 라인

break;

}

}// for()-------------------------------------------------------------------------

System.out.println(value);


// 메시지를 받으면 대기상태에서 해지되도록 한다.

synchronized (session) {

session.notify();

}

}// snmpReceivedPdu()==================================================================


@Override

public void snmpTimeoutError(SnmpSession session, SnmpSyntax pdu) {

System.out.println("Snmp 타임 아웃 ");


// 메시지를 받으면 대기상태에서 해지되도록 한다.

synchronized (session) {

session.notify();

}

}// snmpTimeoutError()=================================================================


public void send(String oid) // 문자열로 OID를 입력받는다.

{

try {

/*

* 데이터를 요구할 OID 정보 생성 SnmpVarBind클래스에 대한 설명은 다음과 같다. This class

* defined the SNMP variables that are transmitted to and from an

* agent. (이 클래스는 에이전트로부터 전달되는 SNMP 변수를 정의한 클래스입니다.) A variable is

* defined by its name (a SnmpObjectId) and its value (SnmpSyntax).

* (변수는 이름(a SnmpObjectId)과 그 이름에 대한 값(SnmpSyntax)에 의해서 정의됩니다.) The

* SnmpVarBind is used by the SnmpPduPacket class and uses

* SnmpObjectId along with any class that implements the SnmpSyntax

* interface. (SnmpVarBind 클래스는 SnmpPduPacket 클래스에서 사용하는 SnmpSyntax

* 인터페이스를 구현한 SnmpObjectId와 함께 사용됩니다)

*/

SnmpVarBind vblist[] = { new SnmpVarBind(oid) };


/*

* SNMP Request를 위한 PDU 생성, SNMP Request방법은 GET으로 정의 SnmpPduRequest에

* 대한 설명은 다음과 같다. The SnmpPduRequest defines the SNMPv1 and SNMPv2

* Protocol Data Unit (PDU) for certian message types.

* (SnmpPduRequest은 certian 메시지 유형에 대한 SNMPv1과 SNMPv2 프로토콜 데이터

* 단위(PDU)를 정의합니다.) The types include: GetRequest, GetNextRequest,

* SetRequest, SNMPv2-Trap, InformRequest, and Response. (형식은 다음과

* 같습니다. : GetRequest, GetNextRequest, SetRequest, SNMPv2-Trap,

* InformRequest 및 Response.) By default the class is constructed as

* a SNMP GetRequest, but can be defined to any of the accepted

* types. (기본적인 클래스는 SNMP GetReqeust로 생성됩니다. 하지만, 허용하는 어떠한 유형으로도 정의할

* 수 있습니다.)

*/

SnmpPduRequest req = new SnmpPduRequest(SnmpPduPacket.GET, vblist);


// SNMP Request에 해당하는 ID를 부여

/*

* 요청을 보낼 때 SNMP는 UDP방식으로 데이터를 전송하기 때문에, 그리고 약간의 응답시간이 존재하기 때문에 요청을

* 보낸 순서대로 응답이 오지 않는다. 순서가 불규칙 하므로 어떤 요청에 대한 응답인지를 알 수 있도록 하기 위해서

* 요청에 Request-id를 set 하여 보내도록 한다.

*/

req.setRequestId(SnmpPduPacket.nextSequence());


// session이라는 이름의 객체변수(SnmpSession)에 대해서 동기화 블록을 걸었다.

synchronized (session) {

// SNMP 에이전트에 데이터를 요청한다.

session.send(req);


// SNMP 데이터를 받을 때까지 대기 상태로 돌입한다. UDP방식이기 때문에 응답시간이 존재한다. 그 사이에

// SnmpSession을 통한 통신(연결)이 끊어지면 안된다.(받을 수 없다.)

session.wait(); // wait() 메소드가 InterruptedExcepion 을 발생시키 때문에 try

// - catch절을 사용함.

}// synchronized()-----------------------------------

}// try--------------------------------------------------

catch (InterruptedException ie) {

} finally {

session.close(); // 오라클DB도 보면 close를 하지 않으면 곤란한 상황이 발생한다.

// (예를 들어서 오라클DB의 경우 쿼리문을 전송했는데 응답이 오지 않는 경우 발생)

// 따라서 finally 예약어를 통해서 예외발생에 상관없이 반드시 close를 할 수 있도록 하였다.

}

}// send()===============================================================================


public static void main(String[] args) throws Exception {

Scanner scanner = new Scanner(System.in);

System.out.print("Agent Address : ");

String agentAddress = scanner.nextLine();


System.out.print("\nCommunity Name : ");

String communityName = scanner.nextLine();

System.out.println("\nOID (주의 : 생략 불가능 끝까지 입력할 것) : ");

String oid = scanner.nextLine();


// main메소드의 매개변수를 통해서 입력받도록 하였다. 추후 스캐너 이용하여 도스에서 입력가능하게 하자.

InetAddress address = InetAddress.getByName(agentAddress);  // agent 주소

SNMPGet snmpGet = new SNMPGet(address, communityName);  // 두번째 String 타입의

// 매개변수는 커뮤니티

// 네임이 들어간다.

snmpGet.send(oid); // 세번째 String 타입의 매개변수는 OID값이다.

}// main()===============================================================================

}//////////////////////////////////////////////////////////////////////////////////////////////