目录
一、介绍SNMP(Simple Network Management Protocol)
简单网络管理协议(SNMP) 是专门设计用于在 IP 网络管理网络节点
(服务器、工作站、路由器、交换机及HUBS等)的一种标准协议,它是一种应用层协议。
注意:SNMP消息全部通过UDP端口161接收,只有Trap信息采用UDP端口162。
要与远程系统交换 SNMP 消息,必须识别该系统,必须指定有关消息交换的重新传输和超时策略信息。通过创建适合要使用的 SNMP 协议的实例,使用 SNMP4J 指定远程系统。
注意:对于 SNMPv1 和 SNMPv2c,除了接口定义的地址、重新传输和超时策略信息外,还必须使用提供必要信息。而对于SNMPv3,必须改用。它扩展了抽象类,并提供以下基于用户的安全模型 (USM) 用户信息:安全名称、安全级别、安全模型(即 USM)和权威引擎 ID。因此,为了能够使用 SNMP4J 发送 SNMP 消息,必须创建一个实例和一个实例。
SNMP 消息是使用 SNMP 接口的实例与 SNMP4J 一起发送的。
要设置实例,只需使用实例调用其构造函数即可。SNMP 会话使用传输映射,通过使用传输协议(例如用户数据报协议 (UDP))向远程系统发送(和接收)SNMP 消息。
默认情况下,SNMP4J 实例支持 SNMP v1、v2c 和 v3。通过子类化这些SNMP协议版本的其他组合,可以得到支持。
使用 SNMP4J,SNMP 消息可以同步(阻塞)和异步(非阻塞)发送。该类不使用内部线程来处理异步和同步请求上的响应。但是,它使用传输映射的接收器线程来处理响应。
异步响应是通过在实现接口的对象实例上调用回调方法来返回的。回调是代表从线路接收响应数据包的传输映射线程执行的。因此,如果被调用的方法阻塞,则在该传输映射的侦听端口上接收的同步和异步消息的传递也将被阻止。其他传输映射将不受影响。通过仅使用同步消息或通过在回调方法中分离处理来避免阻塞。
SNMP4J 通过传输映射的侦听端口接收 SNMP 消息。为了能够接收响应或请求,需要将该端口设置为侦听模式。这必须通过调用实例的方法启动传输映射内部侦听线程来完成。通过调用实例或关联实例上的方法,停止内部线程并关闭侦听端口。
传输映射仅以字节流的形式接收 SNMP 消息,并将消息转发到关联的实例。默认情况下,SNMP4J 使用该类的一个实例来解码和调度传入消息。该实例由类在内部创建和使用。
创建 一 个 并通过调用 来初始化其侦听端口(TransportMappingTransportMapping.listen())
实例化实现接口的类,并通过调用 向实例注册该接口:CommandResponderSnmpSnmp.addCommandResponder(CommandResponder)
当收到未处理的 SNMP 消息(因此是不存在相应未完成请求的 SNMP 消息)时,将使用解码的 PDU 和已解码 SNMP 消息的消息处理模型提供的有关已接收 SNMP 消息的其他信息来调用方法。
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.8.3</version>
</dependency>
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.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.io.IOException;
/**
* 获取设备信息
*
* @author zengLingYao
* @date 2021/12/02
*/
public class GetMessage {
/**
* 获取系统基本信息
*/
public final static String SYS_DESC = "1.3.6.1.2.1.1.1";
/**
* 获取机器名
*/
public final static String SYS_NAME = "1.3.6.1.2.1.1.5";
/**
* 监控时间
*/
public final static String SYS_UPTIME = "1.3.6.1.2.1.1.3";
public static void main(String[] args) {
try {
System.out.println("基本信息:"+getMessageByIpAndOid("192.168.1.94",SYS_DESC));
System.out.println("获取机器名:"+getMessageByIpAndOid("192.168.1.94",SYS_NAME));
System.out.println("监控时间:"+getMessageByIpAndOid("192.168.1.94",SYS_UPTIME));
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getMessageByIpAndOid(String ip, String oid) throws Exception{
String variableString = "";
try{
//设定CommunityTarget
CommunityTarget myTarget = new CommunityTarget();
//机器的地址
Address address = GenericAddress.parse("udp:"+ip+"/161");
//设定地址
myTarget.setAddress(address);
//设置snmp共同体
myTarget.setCommunity(new OctetString("public"));
//设置超时重试次数
myTarget.setRetries(2);
//设置超时的时间
myTarget.setTimeout(5*60);
//设置使用的snmp版本
myTarget.setVersion(SnmpConstants.version2c);
//设定采取的协议
TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
//调用TransportMapping中的listen()方法,启动监听进程,接收消息,由于该监听进程是守护进程,最后应调用close()方法来释放该进程
transport.listen();
//创建SNMP对象,用于发送请求PDU
Snmp protocol = new Snmp(transport);
//创建请求pdu,获取mib
PDU request = new PDU();
//调用的add方法绑定要查询的OID
request.add(new VariableBinding(new OID(oid)));
//调用setType()方法来确定该pdu的类型
request.setType(PDU.GETNEXT);
//调用 send(PDU pdu,Target target)发送pdu,返回一个ResponseEvent对象
ResponseEvent responseEvent = protocol.send(request, myTarget);
//通过ResponseEvent对象来获得SNMP请求的应答pdu,方法:public PDU getResponse()
PDU response=responseEvent.getResponse();
//输出
if(response != null){
//通过应答pdu获得mib信息(之前绑定的OID的值),方法:VaribleBinding get(int index)
VariableBinding vb = response.get(0);
System.out.println(vb);
variableString = String.valueOf(vb.getVariable());
//调用close()方法释放该进程
transport.close();
}
}catch(IOException e){
e.printStackTrace();
}
return variableString;
}
}