最近项目中用到了snmp4j包进行设备拓扑,设备性能监控,本文主要讲解一下SNMP,snmp4j包在Java中的使用。
一、SNMP介绍
SNMP是简单网络管理协议,专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及HUBS等)的一种标准协议,它是一种应用层协议。 SNMP 使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长。通过 SNMP 接收随机消息(及事件报告)网络管理系统获知网络出现问题。目前, SNMP 有 3 种: SNMPV1 、 SNMPV2 、 SNMPV3。第 1 版和第 2 版没有太大差距,但 SNMPV2 是增强版本,包含了其它协议操作。与前两种相比, SNMPV3 则包含更多安全和远程配置。
1、基本操作类型
SNMP对外提供了三种用于控制MIB对象的基本操作命令。它们是:Get、Set 和 Trap。Get:管理站读取代理者处对象的值。它是SNMP协议中使用率最高的一个命令,因为该命令是从网络设备中获得管理信息的基本方式。Set:管理站设置代理者处对象的值。Trap: 代理者主动向管理站通报重要事件。Trap 消息可以用来通知管理站线路的故障、连接的终端和恢复、认证失败等消息,管理站可相应的作出处理。
2、snmp消息组成
一条snmp消息由版本识别符、团体名、PDU组成。版本识别符用于说明现在使用的是哪个版本的SNMP协议,确保SNMP代理使用相同的协议,每个SNMP代理都直接抛弃与自己协议版本不同的数据报。团体名是基本的安全机制,用于实现SNMP网络管理员访问SNMP管理代理时的身份验证。PDU (协议数据单元)是SNMP消息中的数据区, 即Snmp通信时报文数据的载体。PDU指明了SNMP的消息类型及其相关参数。
3、MIB(信息管理库)
上文提到了MIB对象,MIB是信息管理库,可以理解成为agent维护的管理对象数据库, MIB数据对象以一种树状分层结构进行组织,这个树状结构中的每个分支都有一个专用的名字和一个数字形式的标识符,可以通过其数字标识符来查找MIB中的数据对象,这个数字标识符号从结构树的顶部(或根部)开始,直到各个叶 子节点(即数据对象)为止。
4、OID
每个管理对象都有自己的OID(Object Identifier),管理对象通过树状结构进行组织,OID由树上的一系列整数组成,也就是从根节点 通向它的路径,整数之间用点( . )分隔开,树的叶子节点才是真正能够被管理的对象。
二、Java实现SNMP
1、搭建环境
首先本地计算机和被管理的设备要开启snmp,然后下载snmp4j包,或者在maven项目pom文件添加依赖。
2、代码实现
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.*;
public class SNMPUtil {
private String address="udp:192.160.0.2/161";
private String username="admin";
private String authpassword="123";
private String privpassword="123";
private Snmp snmp;
public void initSnmp() throws IOException {
MessageDispatcher messageDispatcher = new MessageDispatcherImpl();
messageDispatcher.addMessageProcessingModel(new MPv1());
messageDispatcher.addMessageProcessingModel(new MPv2c());
OctetString localEngineID=new OctetString(MPv3.createLocalEngineID());
USM usm=new USM(SecurityProtocols.getInstance().addDefaultProtocols(),localEngineID,0);
OctetString userName= new OctetString(username);
OctetString authpass= new OctetString(authpassword);
OctetString privpass= new OctetString(privpassword);
UsmUser user= new UsmUser(userName,AuthMD5.ID,authpass,PrivDES.ID,privpass);
usm.addUser(user.getSecurityName(),user);
messageDispatcher.addMessageProcessingModel(new MPv3(usm));
TransportMapping transportMapping= new DefaultUdpTransportMapping();
snmp = new Snmp(messageDispatcher,transportMapping);
snmp.listen();
}
public Target createTarget(String oid){
Target target=null;
int version=1;
if(!(version==SnmpConstants.version1||version==SnmpConstants.version2c||version==SnmpConstants.version3)){
return target;
}
if(version==SnmpConstants.version3){
target = new UserTarget();
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setSecurityName(new OctetString(this.username));
}else {
target=new CommunityTarget();
target.setSecurityName(new OctetString(this.username));
if(version==SnmpConstants.version2c){
target.setSecurityModel(SecurityModel.SECURITY_MODEL_SNMPv2c);
}
}
target.setVersion(version);
target.setAddress(GenericAddress.parse(this.address));
target.setRetries(3);
target.setTimeout(2000);
return target;
}
public static void setStringVar(PDU pdu,String oid,String var){
OID oidStr = new OID();
oidStr.setValue(oid);
VariableBinding ipBind = new VariableBinding(oidStr,new OctetString(var));
pdu.add(ipBind);
}
public static void setIntVar(PDU pdu,String oid,int var){
OID oidStr = new OID();
oidStr.setValue(oid);
VariableBinding ipBind = new VariableBinding(oidStr,new Integer32(var));
pdu.add(ipBind);
}
public static void setGuage(PDU pdu,String oid,long var){
OID oidStr = new OID();
oidStr.setValue(oid);
VariableBinding ipBind = new VariableBinding(oidStr,new Gauge32(var));
pdu.add(ipBind);
}
public static void setIpAddress(PDU pdu,String oid,String var){
OID oidStr = new OID();
oidStr.setValue(oid);
VariableBinding ipBind = new VariableBinding(oidStr,new IpAddress(var));
pdu.add(ipBind);
}
private static PDU createPDU(int version,int type,String oid){
PDU pdu=null;
if(version==SnmpConstants.version3){
pdu= new ScopedPDU();
}else {
pdu= new PDUv1();
}
pdu.setType(type);
pdu.add(new VariableBinding(new OID(oid)));
return pdu;
}
public List<Map> snmpGet(String oid){
try{
List<Map> list= new ArrayList<Map>();
initSnmp();
Target target = this.createTarget(oid);
PDU pdu=createPDU(1,PDU.GET,oid);
ResponseEvent responseEvent = snmp.send(pdu,target);
PDU response=responseEvent.getResponse();
if(null==response){
System.out.println("Timeout.....");
}else {
if(response.getErrorStatus()==PDU.noError){
Vector<? extends VariableBinding> vbs= response.getVariableBindings();
for (VariableBinding vb: vbs
) {
Map map = new HashMap();
map.put("value",vb.getVariable());
list.add(map);
}
return list;
}else {
System.out.println("Error:"+response.getErrorStatusText());
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public boolean setProprety(String oid) {
boolean bool = false;
try{
initSnmp();
Target target = this.createTarget(oid);
PDU pdu=createPDU(1,PDU.SET,oid);
ResponseEvent responseEvent = snmp.send(pdu, target);
PDU result = responseEvent.getResponse();
if(result!=null){
System.out.println("result:"+result.toString());
if (result.getErrorStatus() == result.noError) {
bool = true;
}
}
}catch (IOException e){
e.printStackTrace();
}
return bool;
}
public void snmpwalk(String oid){
try{
List<Map> list= new ArrayList<Map>();
initSnmp();
Target target = this.createTarget(oid);
PDU pdu=createPDU(1,PDU.GETNEXT,oid);
boolean matched=true;
while (matched){
ResponseEvent responseEvent = snmp.send(pdu,target);
if(responseEvent==null||responseEvent.getResponse()==null){
break;
}
PDU response=responseEvent.getResponse();
String nextOid=null;
Vector<? extends VariableBinding> vbs= response.getVariableBindings();
for (int i = 0; i <vbs.size() ; i++) {
Map map = new HashMap();
VariableBinding vb= vbs.elementAt(i);
Variable variable= vb.getVariable();
nextOid=vb.getOid().toDottedString();
if(!nextOid.startsWith(oid)){
matched=false;
break;
}
map.put("oid",nextOid);
map.put("value",variable);
list.add(map);
}
if(!matched){
break;
}
pdu.clear();
pdu.add(new VariableBinding(new OID(nextOid)));
}
}catch (IOException e){
}
}
class TrapReceiver implements CommandResponder{
private String username = "admin";
private String authPassword = "123";
private String privPassword = "123";
private String address = "udp:192.168.0.15/162";
private MultiThreadedMessageDispatcher dispatcher;
private Snmp snmp = null;
private Address listenAddress;
private ThreadPool threadPool;
private void init() throws UnknownHostException, IOException {
try {
threadPool = ThreadPool.create("Trap", 2);
dispatcher = new MultiThreadedMessageDispatcher(threadPool,
new MessageDispatcherImpl());
listenAddress = GenericAddress.parse(address);
TransportMapping<?> transport;
if (listenAddress instanceof UdpAddress) {
transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
} else {
transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);
}
snmp = new Snmp(dispatcher, transport);
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
SecurityProtocols.getInstance().addDefaultProtocols();
OctetString userName1 = new OctetString(username);
OctetString authPass = new OctetString(authPassword);
OctetString privPass = new OctetString(privPassword);
UsmUser usmUser1 = new UsmUser(userName1, AuthMD5.ID, authPass, PrivAES128.ID, privPass);
UsmUserEntry userEnty1 = new UsmUserEntry(userName1, usmUser1);
UsmUserTable userTable = snmp.getUSM().getUserTable();
userTable.addUser(userEnty1);
snmp.listen();
snmp.addCommandResponder(this);
}catch (Exception e){
e.printStackTrace();
}
}
public void run() {
try {
init();
snmp.addCommandResponder(this);
System.out.println("开始监听Trap信息!");
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void processPdu(CommandResponderEvent respEvnt) {
System.out.println("trap接受到告警消息,开始对消息进行处理");
try {
if (respEvnt != null && respEvnt.getPDU() != null) {
PDU pdu=respEvnt.getPDU();
Vector<? extends VariableBinding> vbs= pdu.getVariableBindings();
for (int i = 0; i <vbs.size() ; i++) {
System.out.println("消息体oid:"+vbs.elementAt(i).getOid());
System.out.println("消息体oid对应值:"+vbs.elementAt(i).getVariable());
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
实际SNMP报文类型还有getBulk,getNext等类型,有兴趣的小伙伴可以自己尝试一下。还有一款MIB Browser(MIB浏览器)是SNMP开发中必备一种工具,有时间再讲一下它的安装和使用。
|