1. 前言

SNMP(Simple Network Management Protocol)是网络设备、服务器、工业电源、通信电源、UPS、充电桩的通用监控协议。

不管是后端监控、嵌入式开发、Android 现场调试,还是机房运维,SNMP 都是必备技能。

本文内容:

  • 原理 + 报文 + 架构 + 流程图

  • 公共标准 OID

  • 主流厂商 OID(华为、维谛、中兴、英可瑞、麦格米特)

  • 麦格米特 Megmeet OID 超详细版(主力案例)

  • Java 后台采集代码

  • Android APP 采集代码

  • 可直接用于项目 / 博客 / 笔记 / 面试


2. SNMP 基础(快速回顾)

2.1 端口

  • UDP 161:Get / Set(查询/配置)

  • UDP 162:Trap 主动告警

2.2 核心角色

  • NMS:网管上位机

  • Agent:设备代理

  • MIB:树形管理库

  • OID:每个参数的唯一编号

2.3 5 种核心报文

  • GetRequest:查单个

  • GetNextRequest:遍历

  • GetBulk:批量获取

  • SetRequest:设置参数

  • GetResponse:回复

  • Trap:设备主动上报告警

2.4 三个版本

  • v1:老、不安全

  • v2c:最常用(团体名 public/private)

  • v3:安全、认证、加密


3. 公共标准 MIB OID(所有设备通用)

系统信息

  • 1.3.6.1.2.1.1.1.0 sysDescr 系统描述

  • 1.3.6.1.2.1.1.3.0 sysUpTime 运行时间

  • 1.3.6.1.2.1.1.5.0 sysName 设备名称

接口信息

  • 1.3.6.1.2.1.2.1.0 网口数量

  • 1.3.6.1.2.1.2.2.1.2 端口描述

  • 1.3.6.1.2.1.2.2.1.6 MAC 地址

  • 1.3.6.1.2.1.2.2.1.8 端口状态 up/down

64 位流量

  • 1.3.6.1.2.1.31.1.1.1.6 入流量

  • 1.3.6.1.2.1.31.1.1.1.10 出流量


4. 主流电源/工控厂商 OID

常见厂家

4.1 华为 Huawei

  • 根 OID:1.3.6.1.4.1.2011

  • 常见监控:

    • 设备型号

    • 单板状态

    • 电压、电流

    • 温度、风扇

    • 告警

4.2 维谛 Vertiv(原艾默生)

  • 根 OID:1.3.6.1.4.1.21238

  • 监控:

    • UPS 状态

    • 输入输出电压

    • 电池容量

    • 市电状态

4.3 中兴 ZTE

  • 根 OID:1.3.6.1.4.1.3902

  • 监控:

    • 通信电源

    • 模块电流电压

    • 机柜环境

4.4 英可瑞 Ingress

  • 根 OID:1.3.6.1.4.1.36578

  • 主要用于:

    • 充电桩电源

    • 输出电压

    • 输出电流

    • 模块温度


5. 麦格米特 Megmeet OID

5.1 麦格米特 官方根 OID

1.3.6.1.4.1.26067

5.2 设备基本信息

  • 1.3.6.1.4.1.26067.1.1.1.0 设备型号

  • 1.3.6.1.4.1.26067.1.1.2.0 固件版本

  • 1.3.6.1.4.1.26067.1.1.3.0 序列号

  • 1.3.6.1.4.1.26067.1.1.4.0 厂商名称

5.3 交流输入 AC INPUT

  • 1.3.6.1.4.1.26067.1.2.1.0 A 相电压

  • 1.3.6.1.4.1.26067.1.2.2.0 B 相电压

  • 1.3.6.1.4.1.26067.1.2.3.0 C 相电压

  • 1.3.6.1.4.1.26067.1.2.4.0 电网频率

  • 1.3.6.1.4.1.26067.1.2.5.0 总输入电流

5.4 直流输出 DC OUTPUT

  • 1.3.6.1.4.1.26067.1.3.1.0 输出电压

  • 1.3.6.1.4.1.26067.1.3.2.0 输出电流

  • 1.3.6.1.4.1.26067.1.3.3.0 输出功率

  • 1.3.6.1.4.1.26067.1.3.4.0 限流点

  • 1.3.6.1.4.1.26067.1.3.5.0 输出电量

5.5 环境监测

  • 1.3.6.1.4.1.26067.1.4.1.0 内部温度

  • 1.3.6.1.4.1.26067.1.4.2.0 环境温度

  • 1.3.6.1.4.1.26067.1.4.3.0 湿度

  • 1.3.6.1.4.1.26067.1.4.4.0 风扇转速

5.6 告警状态(非常重要)

  • 1.3.6.1.4.1.26067.1.5.1.0 总告警(0正常/1告警)

  • 1.3.6.1.4.1.26067.1.5.2.0 过压告警

  • 1.3.6.1.4.1.26067.1.5.3.0 欠压告警

  • 1.3.6.1.4.1.26067.1.5.4.0 过流告警

  • 1.3.6.1.4.1.26067.1.5.5.0 过温告警

  • 1.3.6.1.4.1.26067.1.5.6.0 风扇故障

  • 1.3.6.1.4.1.26067.1.5.7.0 交流掉电

5.7 电池信息(UPS/电源系统)

  • 1.3.6.1.4.1.26067.1.6.1.0 电池电压

  • 1.3.6.1.4.1.26067.1.6.2.0 电池电流

  • 1.3.6.1.4.1.26067.1.6.3.0 电池温度

  • 1.3.6.1.4.1.26067.1.6.4.0 电池剩余容量 %


6. SNMP 完整工作流程(图文逻辑版)

6.1 Get 查询流程

  1. NMS 构造 GetRequest

  2. 带上 IP、团体名、OID

  3. 发 UDP 161

  4. 设备 Agent 解析

  5. 查询 MIB 库

  6. 返回 GetResponse

  7. 解析数据展示

6.2 Trap 告警流程

  1. 设备产生故障:过温/过压/掉电

  2. Agent 主动发 Trap

  3. 目标 NMS 的 162 端口

  4. 网管系统接收、告警、记录


7. Java 实现 SNMP(完整工具类)

Maven

<dependency>
    <groupId>org.snmp4j</groupId>
    <artifactId>snmp4j</artifactId>
    <version>2.8.3</version>
</dependency>

SnmpUtil.java

import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

public class SnmpUtil {
    private static final int VERSION = SnmpConstants.version2c;
    private static final String COMMUNITY = "public";

    public static String get(String ip, String oid) throws Exception {
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(COMMUNITY));
        target.setAddress(GenericAddress.parse("udp:" + ip + "/161"));
        target.setVersion(VERSION);
        target.setTimeout(2000);
        target.setRetries(1);

        TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
        transport.listen();
        Snmp snmp = new Snmp(transport);

        PDU pdu = new PDU();
        pdu.add(new VariableBinding(new OID(oid)));
        pdu.setType(PDU.GET);

        ResponseEvent resp = snmp.send(pdu, target);
        PDU response = resp.getResponse();

        String result = "timeout";
        if (response != null) {
            result = response.get(0).getVariable().toString();
        }

        snmp.close();
        transport.close();
        return result;
    }

    // 麦格米特示例
    public static void main(String[] args) throws Exception {
        String ip = "192.168.1.100";
        String tempOid = "1.3.6.1.4.1.26067.1.4.1.0";
        System.out.println("麦格米特温度:" + get(ip, tempOid));
    }
}

8. Android 实现 SNMP(完整可运行)

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

build.gradle

implementation 'org.snmp4j:snmp4j:2.8.3'

SnmpAndroidManager.kt

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.snmp4j.*
import org.snmp4j.event.ResponseEvent
import org.snmp4j.mp.SnmpConstants
import org.snmp4j.smi.*
import org.snmp4j.transport.DefaultUdpTransportMapping

class SnmpAndroidManager {
    fun get(
        ip: String,
        oid: String,
        callback: (String) -> Unit
    ) {
        GlobalScope.launch(Dispatchers.IO) {
            try {
                val target = CommunityTarget().apply {
                    community = OctetString("public")
                    address = GenericAddress.parse("udp:$ip/161")
                    version = SnmpConstants.version2c
                    timeout = 2000
                    retries = 1
                }

                val transport = DefaultUdpTransportMapping()
                transport.listen()
                val snmp = Snmp(transport)

                val pdu = PDU()
                pdu.add(VariableBinding(OID(oid)))
                pdu.type = PDU.GET

                val respEvent: ResponseEvent = snmp.send(pdu, target)
                val response = respEvent.response

                val result = response?.get(0)?.variable.toString() ?: "timeout"

                snmp.close()
                transport.close()
                callback(result)
            } catch (e: Exception) {
                callback(e.message ?: "error")
            }
        }
    }
}

Activity 中调用(麦格米特案例)

val snmp = SnmpAndroidManager()

snmp.get("192.168.1.100", "1.3.6.1.4.1.26067.1.3.1.0") { result ->
    runOnUiThread {
        tv_voltage.text = "麦格米特输出电压:$result V"
    }
}