当前位置: 代码网 > it编程>编程语言>Java > 使用Java和SNMP4J实现SNMP操作完整代码

使用Java和SNMP4J实现SNMP操作完整代码

2024年12月08日 Java 我要评论
引言snmp(简单网络管理协议)是一种用于网络设备管理的标准协议。本文将介绍如何使用 java 和 snmp4j(一个开源的 snmp 实现库)进行 snmp 操作。我们将通过编写 snmputil

引言

snmp(简单网络管理协议)是一种用于网络设备管理的标准协议。本文将介绍如何使用 java 和 snmp4j(一个开源的 snmp 实现库)进行 snmp 操作。我们将通过编写 snmputil 类来演示如何进行 snmp 初始化、创建 pdu、发送 snmp 请求并处理响应。

环境准备

首先,确保您已经添加了 snmp4j 依赖。可以通过 maven 或 gradle 进行依赖管理。

<dependency>
    <groupid>org.snmp4j</groupid>
    <artifactid>snmp4j</artifactid>
    <version>2.8.6</version>
</dependency>
implementation 'org.snmp4j:snmp4j:2.8.6'

snmputil 类概述

以下是编写 snmputil 类的整体结构。该类提供了静态方法来初始化 snmp、创建 snmp 目标、创建 pdu、发送 snmp 请求和处理响应。

类的静态初始化

我们在这使用静态块来初始化 snmp 对象,确保整个应用程序生命周期中只进行一次初始化。

public class snmputil {
    private static final logger log = loggerfactory.getlogger(snmputil.class);
    private static snmp snmp = null;

    static {
        try {
            initsnmp();
        } catch (ioexception e) {
            log.error("snmp 初始化失败", e);
        }
    }

    private static synchronized void initsnmp() throws ioexception {
        if (snmp == null) {
            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);
            usmuser user = new usmuser(new octetstring("snmpv3"), authsha.id, new octetstring("authpassword"),
                    privaes128.id, new octetstring("privpassword"));
            usm.adduser(user.getsecurityname(), user);
            messagedispatcher.addmessageprocessingmodel(new mpv3(usm));
            transportmapping<?> transportmapping = new defaultudptransportmapping();
            snmp = new snmp(messagedispatcher, transportmapping);
            snmp.listen();
        }
    }
}

创建目标

编写createtarget 方法用于创建 snmp 目标,支持 snmp v1, v2c 和 v3 版本。

private static target createtarget(int version, string community, string ipaddress, int port) {
    target target = null;
    if (!(version == snmpconstants.version3 || version == snmpconstants.version2c || version == snmpconstants.version1)) {
        log.error("参数version异常");
        return target;
    }
    if (version == snmpconstants.version3) {
        target = new usertarget();
        target.setsecuritylevel(securitylevel.auth_priv);
        target.setsecurityname(new octetstring("snmpv3"));
    } else {
        target = new communitytarget();
        ((communitytarget) target).setcommunity(new octetstring(community));
        if (version == snmpconstants.version2c) {
            target.setsecuritymodel(securitymodel.security_model_snmpv2c);
        }
    }
    target.setversion(version);
    target.setaddress(genericaddress.parse("udp:" + ipaddress + "/" + port));
    target.setretries(5);
    target.settimeout(3000);
    return target;
}

创建 pdu

编写createpdu 方法用于创建 protocol data unit (pdu),这是 snmp 消息的基本构成单元。

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;
}

private static pdu createpdu(int version, int type, list<string> oids) {
    pdu pdu = null;
    if (version == snmpconstants.version3) {
        pdu = new scopedpdu();
    } else {
        pdu = new pdu();
    }
    pdu.settype(type);
    for (string oid : oids) {
        pdu.add(new variablebinding(new oid(oid)));
    }
    return pdu;
}

发送 snmp 请求

编写snmpwalk 方法用于发送 getnext 请求,并处理响应。此处注意,不一定都是用getnext请求,也可以用get请求,两者区别故名思义,一个是获取下一条oid,一个是获取自己本身

public static pdu snmpwalk(string ipaddr, int port, int version, string community, string oid) {
    try {
        target target = createtarget(version, community, ipaddr, port);
        pdu pdu = createpdu(version, pdu.getnext, oid);
        responseevent responseevent = snmp.send(pdu, target);
        pdu response = responseevent.getresponse();
        return response;
    } catch (ioexception e) {
        log.error("snmp 发送请求失败", e);
        return new pdu();
    }
}

public static pdu snmpwalk(string ipaddr, int port, int version, string community, list<string> oids) {
    try {
        target target = createtarget(version, community, ipaddr, port);
        pdu pdu = createpdu(version, pdu.getnext, oids);
        responseevent responseevent = snmp.send(pdu, target);
        pdu response = responseevent.getresponse();
        return response;
    } catch (ioexception e) {
        log.error("snmp 发送请求失败", e);
        return new pdu();
    }
}

处理 snmp 响应

编写snmpwalkall 和 snmpwalksegment 方法用于处理连续的 snmp 响应,直到到达 mib 的末尾。

public static list<variablebinding> snmpwalkall(string ipaddr, int port, int version, string community, string startoid) {
    list<variablebinding> results = new arraylist<>();
    target target = createtarget(version, community, ipaddr, port);
    pdu pdu = new pdu();
    pdu.add(new variablebinding(new oid(startoid)));

    while (true) {
        try {
            pdu.settype(pdu.getnext);
            responseevent responseevent = snmp.send(pdu, target);
            pdu response = responseevent.getresponse();

            if (response != null && response.size() > 0 && response.geterrorstatus() == 0) {
                if (response.get(0).getvariable().tostring().equals("endofmibview")) {
                    break;
                }
                results.addall(response.getvariablebindings());
                pdu.setrequestid(null); // reset request id for the next request
                pdu.remove(0); // remove the old request
                pdu.add(response.get(0)); // add the new request based on the last response
            } else {
                break;
            }
        } catch (ioexception e) {
            log.error("snmp 发送请求失败", e);
            break;
        }
    }
    return results;
}
// ...其他代码见完整代码

完整代码

import org.slf4j.logger;
import org.slf4j.loggerfactory;
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.genericaddress;
import org.snmp4j.smi.oid;
import org.snmp4j.smi.octetstring;
import org.snmp4j.smi.variablebinding;
import org.snmp4j.transport.defaultudptransportmapping;

import java.io.ioexception;
import java.util.arraylist;
import java.util.list;

public class snmputil {
    private static final logger log = loggerfactory.getlogger(snmputil.class);
    private static snmp snmp = null; // 将共享资源的访问控制为静态初始化

    static {
        // 将 snmp 对象的初始化放在静态块中,确保只初始化一次
        try {
            initsnmp();
        } catch (ioexception e) {
            log.error("snmp 初始化失败", e); // 记录初始化失败的异常信息
        }
    }

    private static synchronized void initsnmp() throws ioexception { // 添加 synchronized 关键字保证线程安全
        if (snmp == null) {
            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);
            usmuser user = new usmuser(new octetstring("snmpv3"), authsha.id, new octetstring("authpassword"),
                    privaes128.id, new octetstring("privpassword"));
            usm.adduser(user.getsecurityname(), user);
            messagedispatcher.addmessageprocessingmodel(new mpv3(usm));
            transportmapping<?> transportmapping = new defaultudptransportmapping();
            snmp = new snmp(messagedispatcher, transportmapping);
            snmp.listen();
        }
    }

    private static target createtarget(int version, string community, string ipaddress, int port) {
        target target = null;
        if (!(version == snmpconstants.version3 || version == snmpconstants.version2c || version == snmpconstants.version1)) {
            log.error("参数version异常"); // 保持错误日志记录
            return target;
        }
        if (version == snmpconstants.version3) {
            target = new usertarget();
            target.setsecuritylevel(securitylevel.auth_priv);
            target.setsecurityname(new octetstring("snmpv3"));
        } else {
            target = new communitytarget();
            ((communitytarget) target).setcommunity(new octetstring(community));
            if (version == snmpconstants.version2c) {
                target.setsecuritymodel(securitymodel.security_model_snmpv2c);
            }
        }
        target.setversion(version);
        target.setaddress(genericaddress.parse("udp:" + ipaddress + "/" + port));
        target.setretries(5);
        target.settimeout(3000);
        return target;
    }

    /**
     * 创建 pdu 对象
     * @param version
     * @param type
     * @param oid
     * @return
     */
    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;
    }

    /**
     * 创建 pdu 对象
     * @param version
     * @param type
     * @param oids
     * @return
     */
    private static pdu createpdu(int version, int type, list<string> oids) {
        pdu pdu = null;
        if (version == snmpconstants.version3) {
            pdu = new scopedpdu();
        } else {
            pdu = new pdu();
        }
        pdu.settype(type);
        for (string oid : oids) {
            pdu.add(new variablebinding(new oid(oid)));
        }
        return pdu;
    }

    /**
     * 获取 snmp 响应
     * @param ipaddr
     * @param port
     * @param version
     * @param community
     * @param oid
     * @return
     */
    public static pdu snmpwalk(string ipaddr, int port, int version, string community, string oid) {
        try {
            // 由于 snmp 对象已在静态块中初始化,这里不再需要调用 initsnmp
            target target = createtarget(version, community, ipaddr, port);
            pdu pdu = createpdu(version, pdu.getnext, oid); // 保持内部字符串不变
            responseevent responseevent = snmp.send(pdu, target);
            pdu response = responseevent.getresponse();
            return response;
        } catch (ioexception e) {
            log.error("snmp 发送请求失败", e); // 增加异常日志记录
            return new pdu(); // 在异常情况下仍然返回一个新的 pdu 对象,但已记录错误信息
        }
    }

    /**
     * 获取 snmp 响应
     * @param ipaddr
     * @param port
     * @param version
     * @param community
     * @param oids
     * @return
     */
    public static pdu snmpwalk(string ipaddr, int port, int version, string community, list<string> oids) {
        try {
            // 由于 snmp 对象已在静态块中初始化,这里不再需要调用 initsnmp
            target target = createtarget(version, community, ipaddr, port);
            pdu pdu = createpdu(version, pdu.getnext, oids); // 保持内部字符串不变
            responseevent responseevent = snmp.send(pdu, target);
            pdu response = responseevent.getresponse();
            return response;
        } catch (ioexception e) {
            log.error("snmp 发送请求失败", e); // 增加异常日志记录
            return new pdu(); // 在异常情况下仍然返回一个新的 pdu 对象,但已记录错误信息
        }
    }

    /**
     * 获取 snmp 响应
     * @param ipaddr
     * @param port
     * @param version
     * @param community
     * @param startoid
     * @return
     */
    public static list<variablebinding> snmpwalkall(string ipaddr, int port, int version, string community, string startoid) {
        list<variablebinding> results = new arraylist<>();
        target target = createtarget(version, community, ipaddr, port);
        pdu pdu = new pdu();
        pdu.add(new variablebinding(new oid(startoid)));

        while (true) {
            try {
                pdu.settype(pdu.getnext);
                responseevent responseevent = snmp.send(pdu, target);
                pdu response = responseevent.getresponse();

                if (response != null && response.size() > 0 && response.geterrorstatus() == 0) {
                    if (response.get(0).getvariable().tostring().equals("endofmibview")) {
                        break;
                    }
                    results.addall(response.getvariablebindings());
                    pdu.setrequestid(null); // reset request id for the next request
                    pdu.remove(0); // remove the old request
                    pdu.add(response.get(0)); // add the new request based on the last response
                } else {
                    break;
                }
            } catch (ioexception e) {
                log.error("snmp 发送请求失败", e);
                break;
            }
        }
        return results;
    }

    /**
     * 获取 snmp 响应
     * @param ipaddr
     * @param port
     * @param version
     * @param community
     * @param startoid
     * @return
     */
    public static list<variablebinding> snmpwalksegment(string ipaddr, int port, int version, string community, string startoid) {
        list<variablebinding> results = new arraylist<>();
        target target = createtarget(version, community, ipaddr, port);
        pdu pdu = new pdu();
        pdu.add(new variablebinding(new oid(startoid)));

        while (true) {
            try {
                pdu.settype(pdu.getnext);
                responseevent responseevent = snmp.send(pdu, target);
                pdu response = responseevent.getresponse();

                if (response != null && response.size() > 0 && response.geterrorstatus() == 0) {
                    variablebinding vb = response.get(0);
                    results.add(vb);

                    // check if we have reached the end of the branch
                    if (!vb.getoid().startswith(new oid(startoid)) || vb.getvariable().tostring().equals("endofmibview")) {
                        break;
                    }

                    pdu.setrequestid(null); // reset request id for the next request
                    pdu.remove(0); // remove the old request
                    pdu.add(vb); // add the new request based on the last response
                    system.out.println("oid: " + vb.getoid() + ", value: " + vb.getvariable());
                } else {
                    break;
                }
            } catch (ioexception e) {
                log.error("snmp 发送请求失败", e);
                break;
            }
        }
        return results;
    }

    public static list<variablebinding> snmpwalksegment(string ipaddr, int port, int version, string community, list<string> startoids) {
        list<variablebinding> results = new arraylist<>();
        target target = createtarget(version, community, ipaddr, port);

        for(string startoid: startoids){
            pdu pdu = new pdu();
            pdu.add(new variablebinding(new oid(startoid)));
            while (true) {
                try {
                    pdu.settype(pdu.getnext);
                    responseevent responseevent = snmp.send(pdu, target);
                    pdu response = responseevent.getresponse();

                    if (response != null && response.size() > 0 && response.geterrorstatus() == 0) {
                        variablebinding vb = response.get(0);
                        results.add(vb);

                        // check if we have reached the end of the branch
                        if (!vb.getoid().startswith(new oid(startoid)) || vb.getvariable().tostring().equals("endofmibview")) {
                            break;
                        }

                        pdu.setrequestid(null); // reset request id for the next request
                        pdu.remove(0); // remove the old request
                        pdu.add(vb); // add the new request based on the last response
                        system.out.println("oid: " + vb.getoid() + ", value: " + vb.getvariable());
                    } else {
                        break;
                    }
                } catch (ioexception e) {
                    log.error("snmp 发送请求失败", e);
                    break;
                }
            }
        }

        return results;
    }


    public static void main(string[] args) {
        pdu response = snmputil.snmpwalk("127.0.0.1", 161, snmpconstants.version2c, "public", ".1");
        if (response != null && response.geterrorstatus() == 0) {
            for (variablebinding vb : response.getvariablebindings()) {
                system.out.println("oid: " + vb.getoid() + ", value: " + vb.getvariable());
            }
        } else {
            system.out.println("error in response: " + response.geterrorstatustext());
        }
    }
}

总结

通过本文的讲解,您应该已经掌握了如何使用 java 和 snmp4j 库进行 snmp 操作。我们介绍了 snmputil 类的设计和实现,包括 snmp 初始化、创建目标、创建 pdu、发送 snmp 请求和处理响应等内容。希望这篇教程能够帮助您更好地理解和使用 snmp4j 进行网络设备管理

到此这篇关于使用java和snmp4j实现snmp操作的文章就介绍到这了,更多相关java和snmp4j实现snmp内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com