You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何同时保持多个Net-SNMP会话持续开启?

关于Net-SNMP多会话持久化的解决方案

完全可以在程序运行全程保持每个客户端的SNMP会话持续开启,你之前对Net-SNMP会话管理的认知存在偏差——Net-SNMP支持同时维护多个独立的SNMP会话,每个会话对应一个客户端主机,无需关闭旧会话才能开启新会话。

核心实现思路

  • 为每个客户端维护独立的netsnmp_session实例:用容器(比如std::map<std::string, netsnmp_session*>)存储所有会话句柄,键可设为主机IP或名称,便于快速查找。
  • 程序启动时批量初始化会话:调用snmp_sess_open()为每个客户端创建会话,成功后将句柄存入容器。
  • 轮询复用已有会话:每分钟轮询时,直接使用容器中保存的会话句柄发起请求,省去重复打开/关闭会话的开销。
  • 程序退出统一清理:遍历容器调用snmp_sess_close()逐一关闭所有会话。

关键注意事项

  • 会话故障重连:长时间保持会话可能因网络波动、主机重启导致会话失效,轮询时需检查请求状态,一旦失败则调用snmp_sess_open()重建会话。
  • 独立会话配置:每个会话的版本、社区串、超时时间等参数需独立初始化,避免结构体复用引发的配置冲突。
  • 异步API优化:如果客户端数量较多,推荐使用Net-SNMP的异步API(如snmp_sess_async_send()),可以更高效地处理多会话并发轮询。

简化代码示例

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <map>
#include <string>
#include <vector>

// 存储各主机的会话句柄
std::map<std::string, netsnmp_session*> g_sessions;

// 初始化单个主机的SNMP会话
netsnmp_session* init_snmp_session(const std::string& host, const std::string& community) {
    netsnmp_session session_template, *session_ptr;
    snmp_sess_init(&session_template);
    
    session_template.peername = const_cast<char*>(host.c_str());
    session_template.community = const_cast<unsigned char*>(community.c_str());
    session_template.community_len = community.size();
    session_template.version = SNMP_VERSION_2c;
    session_template.timeout = 1000000; // 1秒超时
    session_template.retries = 2;

    if (!(session_ptr = snmp_sess_open(&session_template))) {
        snmp_perror("Failed to open session for host");
        return nullptr;
    }
    return session_ptr;
}

// 批量初始化所有客户端会话
void init_all_sessions(const std::vector<std::string>& hosts, const std::string& community) {
    for (const auto& host : hosts) {
        auto sess = init_snmp_session(host, community);
        if (sess) {
            g_sessions[host] = sess;
        }
    }
}

// 轮询单个会话获取IF-MIB数据(以ifInOctets为例)
void poll_session(netsnmp_session* sess) {
    netsnmp_pdu *request_pdu = snmp_pdu_create(SNMP_MSG_GET);
    if (!request_pdu) return;

    // 添加要查询的OID:ifInOctets(第一个网络接口)
    oid if_in_octets[] = {1,3,6,1,2,1,2,2,1,10,1};
    snmp_add_var(request_pdu, if_in_octets, OID_LENGTH(if_in_octets), ASN_COUNTER, nullptr);

    netsnmp_pdu* response_pdu = nullptr;
    int status = snmp_sess_synch_response(sess, request_pdu, &response_pdu);

    if (status == STAT_SUCCESS && response_pdu && response_pdu->errstat == SNMP_ERR_NOERROR) {
        // 处理返回的统计数据
        netsnmp_variable_list* vars = response_pdu->variables;
        if (vars) {
            // 根据OID类型解析值,此处为计数器类型
            u_long in_octets = *vars->val.counter64->high << 32 | *vars->val.counter64->low;
            printf("Incoming octets: %lu\n", in_octets);
        }
    } else {
        // 会话失效,标记待重建(此处简化处理,实际可加入重连逻辑)
        printf("Poll failed, session may be invalid\n");
    }

    if (response_pdu) snmp_free_pdu(response_pdu);
}

// 轮询所有客户端会话
void poll_all_clients() {
    for (auto& [host, sess] : g_sessions) {
        printf("Polling host: %s\n", host.c_str());
        poll_session(sess);
    }
}

// 清理所有会话
void cleanup_sessions() {
    for (auto& [host, sess] : g_sessions) {
        snmp_sess_close(sess);
    }
    g_sessions.clear();
}

int main() {
    // 初始化SNMP库
    init_snmp("snmp_poller");

    // 客户端列表示例
    std::vector<std::string> hosts = {"192.168.1.10", "192.168.1.11", "192.168.1.12"};
    std::string community = "public";

    // 初始化所有会话
    init_all_sessions(hosts, community);

    // 模拟每分钟轮询(实际可使用定时器实现)
    while (true) {
        poll_all_clients();
        sleep(60);
    }

    // 清理资源(实际程序退出时执行)
    cleanup_sessions();
    return 0;
}

内容的提问来源于stack exchange,提问作者J.Maduka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 10:34:56