Java进行SNMP通信的指南.docx

上传人:b****6 文档编号:3321510 上传时间:2022-11-21 格式:DOCX 页数:22 大小:66.77KB
下载 相关 举报
Java进行SNMP通信的指南.docx_第1页
第1页 / 共22页
Java进行SNMP通信的指南.docx_第2页
第2页 / 共22页
Java进行SNMP通信的指南.docx_第3页
第3页 / 共22页
Java进行SNMP通信的指南.docx_第4页
第4页 / 共22页
Java进行SNMP通信的指南.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

Java进行SNMP通信的指南.docx

《Java进行SNMP通信的指南.docx》由会员分享,可在线阅读,更多相关《Java进行SNMP通信的指南.docx(22页珍藏版)》请在冰豆网上搜索。

Java进行SNMP通信的指南.docx

Java进行SNMP通信的指南

 

Java进行SNMP通信的指南

1.概述

在网络通信中,我们会经常遇到支持SNMP协议的网络设备打交道,支持SNMP协议的网络设备有很多,如各种带操作系统的服务器、路由器、交换机等,装有UNIX操作系统中的服务器一般都会支持SNMP协议,Windows操作系统的服务器也可以通过”控制面板->添加/删除程序->添加/删除Windows组件->管理和监视工具”中安装SNMP组件,如下图所示。

图1-1

本文的目的不在于讲解SNMP的原理,关于SNMP的原理及其信息组织结构MIB的详细资料,网上的资料很多,本文的目的就是针对在Java环境下解决如何实现SNMP客户端的调用操作以及如何实现SNMP服务器的简单模拟,把笔者的一些经验分享给大家。

2.实现过程

我们知道,SNMP协议是基于UDP协议的,RFC-1157就是SNMP协议详细规范,SNMP协议经历了3个版本,分别是SNMPV1、SNMPV2和SNMPV3。

SNMPV1是一种简单的请求/响应协议,网络管理系统发出一个请求,管理器则返回一个响应,支持GET、GETNEXT、SET和TRAP这4种操作;SNMPV2在SNMPV1的基础上还新增了两种新操作,GETBULK和INFORM;SNMPV3中增加了安全管理方式及远程控制。

由于SNMPV3的安全控制设置起来比较麻烦,所以一些被管设备不支持SNMPV3,而SNMPV1对于大数据量处理有缺陷,所以大部分被管设备都支持SNMPV2,应用得比较多的也是SNMPV2。

JDK提供了对于UDP的编程的支持,分别是数据报套接字(DatagramSocket)和数据包(DatagramPacket),直接采用这些类可以实现对SNMP协议的操作调用,但是正如西方国家一句谚语“不要重复发明轮子(Don’tReinventtheWheel)”,我们没有必要从头开始在设计如何通过Java来实现SNMP,开源源代码的阵营里有好多工具包已经帮我们做掉这件事情了,其中比较出名的有joeSNMP、SNMP4J、iReasoningJavaSNMPAPI等,笔者采用的是SNMP4J,利用SNMP4J可以实现多种SNMP的应用,如客户端调用、Trap的收发、服务端模拟,下面我们就详细讲解如何通过SNMP4J来实现客户端及模拟器(服务端)的应用。

2.1.SNMP4J介绍

我们用到了SNMP4J的几个基础类:

org.snmp4j.TransportMapping;

org.snmp4j.Snmp;

org.snmp4j.smi.Address;

org.snmp4j.Target;

TransportMapping类是对传输层的封装,对UDP封装为DefaultUdpTransportMapping,TCP封装为DefaultTcpTransportMapping,TransportMapping只定义传输的接口,由于SNMP默认采用UDP作为传输协议,所以笔者感觉DefaultTcpTransportMapping不会被用到。

Snmp类是SNMP4J的核心,它提供了发送和接收SNMPPDUs的方法,所有的SNMPPDU类型都可以采用同步或者异步的方式被发送。

PDU.javaimplementsBERSerializable//SNMPv2的报文,提供了编码时需要的信息(个人觉得编码信息可以由工具类提供,对用户会混淆)。

报文结构参见ScopedPDU(v3)。

AddressIP地址和端口(和的不同),常用实现是UdpAddress。

Target发送的时候要用到,包含Address,超时、重试次数、SNMP的版本,常用实现是ComunityTarget,可以指定readcommunity及writecommunity。

2.2.实现客户端

2.2.1.初始化

首先定义类变量,DATATYPE常量的定义是在SET操作里用到的,代码如下:

代码:

/**TransportMapping*/

privateTransportMappingtransport;

/**プロトコール*/

privateSnmpprotocol;

/*DateType定義*/

/**Counter32*/

publicstaticfinalintDATATYPE_COUNTER32=0;

/*Counter64*/

publicstaticfinalintDATATYPE_COUNTER64=1;

/**Gauge32*/

publicstaticfinalintDATATYPE_GAUGE32=2;

/**GenericAddress*/

publicstaticfinalintDATATYPE_GENERICADDRESS=3;

/**Integer32*/

publicstaticfinalintDATATYPE_INTEGER32=4;

/**IpAddress*/

publicstaticfinalintDATATYPE_IPADDRESS=5;

/**OctetString*/

publicstaticfinalintDATATYPE_OCTETSTRING=6;

/**TimeTicks*/

publicstaticfinalintDATATYPE_TIMETICKS=7;

/**UnsignedInteger32*/

publicstaticfinalintDATATYPE_UNSIGNEDINTEGER32=8;

代码段2.2.1-1

初始化,代码如下:

代码:

/**

*初期化

*

*@throwsSmsTerminalException

*アプリエラー

*/

privatevoidinit()throwsSmsTerminalException{

try{

transport=newDefaultUdpTransportMapping();

protocol=newSnmp(transport);

}catch(IOExceptionex){

thrownewSmsTerminalException("initerror",Constants.EXIT_CODE_NORMAL,ex);

}

}

代码段2.2.1-2

2.2.2.GET/GETNEXT操作

SnmpVO是一个简单的JavaBean,包含了以下属性

∙ipAddress(目标机器IP地址);

∙port(端口);

∙retry(重试次数);

∙timeout(超时时间);

∙oid(要获取属性的OID);

∙type(操作类型,默认是GET);

∙communityGet(GET操作的团体字符串);

∙communitySet(SET操作的团体字符串);

GET/GETNEXT操作的代码如下:

代码:

/**

*MIB情報を取得する

*

*@paramsnmpVo

*SNMP相関情報

*@returnoutValue

*SNMP取得結果

*

*@throwsSmsTerminalException

*アプリエラー

*/

publicStringgetSnmpValue(SnmpVOsnmpVo)throwsSmsTerminalException{

log.debug("getSnmpValuestart");

StringoutValue="";

try{

CommunityTargetmyTarget=setTarget(snmpVo,false);

transport.listen();

PDUrequest=setRequest(snmpVo);

PDUresponse=null;//PDUresponse

ResponseEventresponseEvent=protocol.send(request,myTarget);

if(snmpSendReceiveListener!

=null){

snmpSendReceiveListener.beforeReceive();

}

//SNMP受信

response=responseEvent.getResponse();

if(response!

=null){

if(response.getErrorIndex()==PDU.noError

&&response.getErrorStatus()==PDU.noError){//正常場合

VariableBindingvb=response.get(0);

if(vb.isException()){

thrownewSmsTerminalException(vb.getVariable().toString(),

Constants.EXIT_CODE_NORMAL,responseEvent.getError());

}

outValue=vb.getVariable().toString();

}else{//エラー発生

thrownewSmsTerminalException(responseEvent.getError().getMessage(),

Constants.EXIT_CODE_NORMAL,responseEvent.getError());

}

}else{//タイムアウト

thrownewSmsTerminalTimeoutException("SNMP受信タイムアウト");

}

}catch(IOExceptionex){

thrownewSmsTerminalException("getSnmpValueIOerror",Constants.EXIT_CODE_NORMAL,ex);

}finally{

try{

if(protocol!

=null){

protocol.close();

}

if(transport!

=null&&transport.isListening()){

transport.close();

}

}catch(IOExceptionex){

thrownewSmsTerminalException("closeprotocolortransporterror",

Constants.EXIT_CODE_NORMAL,ex);

}

}

log.debug("getSnmpValueend");

returnoutValue;

}

代码段2.2.2-1

其中用到了setTarget方法,采用ComunityTarget设置目标设备IP和端口、Community、SNMP版本、重试次数、超时时间,代码如下:

代码:

/**

*CommunityTargetの設定

*

*@paramsnmpVo

*SNMP相関情報

*@paramisSetOperationSET操作かどうか

*@returnmyTarget

*設定したCommunityTarget

*

*/

privateCommunityTargetsetTarget(SnmpVOsnmpVo,booleanisSetOperation){

CommunityTargetmyTarget=newCommunityTarget();

AddressdeviceAdd;

deviceAdd=GenericAddress.parse(snmpVo.getIpAddress()+"/"

+snmpVo.getPort());

myTarget.setAddress(deviceAdd);//address

if(isSetOperation){

if(StringConverter.nullCheckString(snmpVo.getCommunitySet())){

myTarget.setCommunity(newOctetString(snmpVo.getCommunitySet()));//communitySet

}

}else{

if(StringConverter.nullCheckString(snmpVo.getCommunityGet())){

myTarget.setCommunity(newOctetString(snmpVo.getCommunityGet()));//communityGet

}

}

if(snmpVo.getRetry()!

=0){

myTarget.setRetries(snmpVo.getRetry());//retries

}

if(snmpVo.getTimeout()!

=0){

myTarget.setTimeout(snmpVo.getTimeout());//timeout

}

//intversion=SnmpConstants.ver;

if(StringConverter.nullCheckString(snmpVo.getCommunityGet())

&&("2c".equals(snmpVo.getVer())||"1".equals(snmpVo.getVer()))){

myTarget.setVersion(SnmpConstants.version2c);//org.snmp4j.mp.*

}

returnmyTarget;

}

代码段2.2.2-2

还有setRequest方法,代码如下:

代码:

/**

*OIDの設定

*

*@paramsnmpVo

*SNMP相関情報

*@returnoutValue

*設定したVariableBinding

*

*/

privatePDUsetRequest(SnmpVOsnmpVo){

PDUrequest=newPDU();

VariableBindingvar;

//oidを設定する

var=newVariableBinding(newOID(snmpVo.getOid()));

request.add(var);

//情報取得方式を設定する

request.setType(snmpVo.getType());

if(snmpVo.getType()==0){

request.setType(PDU.GET);//DefaultPDUtypeisGET.

}

returnrequest;

}

代码段2.2.2-3

2.2.3.SET操作

Set操作的代码如下:

代码:

/**

*MIB情報を設定する

*@authorhonghui

*@paramsnmpVo

*SNMP相関情報

*@paramvalue

*SNMP設定内容

*@paramdataTypeデータのタイプ

*@throwsSmsTerminalException

*アプリエラー

*/

publicvoidsetSnmpValue(SnmpVOsnmpVo,Stringvalue,intdataType)

throwsSmsTerminalException{

log.debug("setSnmpValuestart");

try{

CommunityTargetmyTarget=setTarget(snmpVo,true);

transport.listen();

PDUrequest=newPDU();

OIDoid=newOID(snmpVo.getOid());

Variablevariable=getDataTypeVariable(value,dataType);

if(variable==null){

thrownewSmsTerminalException("InvaliddataType:

"+dataType,

Constants.EXIT_CODE_NORMAL,null);

}

request.add(newVariableBinding(oid,variable));

request.setType(PDU.SET);

PDUresponse=null;//PDUresponse

ResponseEventresponseEvent=protocol.send(request,myTarget);

if(snmpSendReceiveListener!

=null){

snmpSendReceiveListener.beforeReceive();

}

//SNMP受信

response=responseEvent.getResponse();

if(response!

=null){

if(response.getErrorIndex()==PDU.noError

&&response.getErrorStatus()==PDU.noError){

//正常場合

}else{//エラー発生

thrownewSmsTerminalException(responseEvent.getError().getMessage(),

Constants.EXIT_CODE_NORMAL,responseEvent.getError());

}

}else{//タイムアウト

thrownewSmsTerminalTimeoutException("SNMP受信タイムアウト");

}

}catch(IOExceptionex){

thrownewSmsTerminalException("setSnmpValueIOerror",Constants.EXIT_CODE_NORMAL,ex);

}finally{

try{

if(protocol!

=null){

protocol.close();

}

if(transport!

=null&&transport.isListening()){

transport.close();

}

}catch(IOExceptionex){

thrownewSmsTerminalException("closeprotocolortransporterror",

Constants.EXIT_CODE_NORMAL,ex);

}

}

}

代码段2.2.3-1

Set操作调用到了getDataTypeVariable方法,需要把传入的dataType转换成SNMP4J的Variable,代码如下:

代码:

/**

*Variableを変換です

*@authorhonghui

*@paramvalueSNMP設定内容

*@paramdataTypeデータのタイプ

*@returnVariable

*/

privateVariablegetDataTypeVariable(Stringvalue,intdataType){

switch(dataType){

caseDATATYPE_COUNTER32:

returnnewCounter32(Long.parseLong(value));

caseDATATYPE_COUNTER64:

returnnewCounter64(Long.parseLong(value));

caseDATATYPE_GAUGE32:

returnnewGauge32(Long.parseLong(value));

caseDATATYPE_GENERICADDRESS:

returnnewGenericAddress();

caseDATATYPE_INTEGER32:

returnnewInteger32(Integer.parseInt(value));

caseDATATYPE_IPADDRESS:

returnnewIpAddress(value);

caseDATATYPE_OCTETSTRING:

returnnewOctetString(value);

caseDATATYPE_TIMETICKS:

returnnewTimeTicks(Long.parseLong(value));

caseDATATYPE_UNSIGNEDINTEGER32:

returnnewUnsignedInteger32(Long.parseLong(value));

}

returnnull;

}

代码段2.2.3-2

2.3.实现模拟器

模拟器(或者说是服务端)的作用很明显,就是在服务器上开启一个监听SNMP的服务,当有客户端的请求时,返回一些结果。

如果模拟器做的很完美的话,客户端连接某个服务器获取或设置SNMP信息时,并没有觉察服务器是真实的还是模拟出来的。

在我们的运用中,只是简单的模拟了GET、GETNEXT和SET这3个操作,对于GET/GETNEXT操作来说,请求后返回的数据也是从数据文件里读取到的,数据文件就是一个普通的CSV文件,内容如下:

数据文件(CSV):

OID,MIB情報

"1.3.6.1.2.1.1.6.0","Beijing2008"

"1.3.6.1.2.1.1.7.0","Olympic"

代码段2.3-1

由于我们只是简单的模拟,所以GET和GETNEXT操作返回的结果是相同的(如果要做成不同的,就要对OID进行排序处理)。

对于SET操作来说,没有返回,如果SET出错,就会抛出异常。

模拟器的代码不多,处理类的全部代码如下:

代码:

/**

*CMTS_SNMPシミュレーター処理クラス

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 法学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1