Qt Creator平台编译snmp++

声明 :本文的大部分资源参考自文章,编译snmp++的方法我也是在这里学习的,结合自己的需求,做了snmp++和Agent++的混合编译。需要了解更多的详情可以点击链接去看原文,我总结了自己的编译过程,并写下此文作为一个回国笔记,希望能帮助到同样有此需求的人。

一 前期准备

操作系统:win11
qt版本:5.8,QtCreator版本为4.2.1
编译器版本:5.8.0_MinGW_32_bit

二 源码准备

准备snmp++和des和 agent++的源码。snmp++就是实现snmp功能的主要代码,des是用来加密算法,agent++写代理的时候用得着。建议和snmp++一起编译了。
下载地址官网
在这里插入图片描述
下载文件然后解压。绿色框的地方点开是对应的开发文档。右下角有一个agent++的帮助文档,建议需要开发的朋友一并下载了。

三 配置编译环境

(一).工程文件建立

1.新建一个Qt工程文件
1.选择创建c++Library
在这里插入图片描述
2.命名工程,这里命名为snmp_dev
在这里插入图片描述
3.创建共享库,Shared Library
在这里插入图片描述
4.选择编译器为mingw。
在这里插入图片描述

(二).将snmp++和Agent++ 源代码复制进来

1.打开刚才解压后的snmp++和agent++文件夹,分别将下属三部分内容复制
snmp++文件夹目录
Agent++文件夹目录
2.先看看snmp++的include中的内容。可见,snmp__pp文件夹,该文件夹中包含了绝大部分的头文件,将该文件夹(snmp_pp)复制,粘贴至刚创建的snmp_dev工程目录下,Agent++目录的操作也是一样的。
在这里插入图片描述
3.打开snmp++的src文件,可以看见一堆的cpp文件,将该部分所有的cpp文件,复制到snmp_dev工程目录下,Agent++的文件操作也是一样的
在这里插入图片描述
4.此使,snmp_dev工程文件下,可以看见如下的部分内容,有一部分将在后续过程中,再复制进来
![这个已经是我编译过的文件了,所以会有些多的东西](https://i-blog.csdnimg.cn/direct/32c9ec964d234ed684d49865d9662c75.png](https://i-blog.csdnimg.cn/direct/ef94e1e89cbe4fbc9ed930fe41eb3445.png)
5.将所有.h和.cpp文件导入工程中

在这里插入图片描述
6.到这一步,导入就暂时告一段落。

(三).修改工程文件的一些内容

1.刚创建的snmp_dev工程中,同时生成的有snmp_dev.h与snmp_dev.cpp。下面需要修改这两个文件内容。
2.删除snmp_dev.cpp。
3.修改snmp_dev.h头文件,删除部分内容,添加一个include,修改至如图,务必要修改。
在这里插入图片描述
4.至此,就可以点击一下左下角哪个锤子按钮,开始尝试编译了,当然,会有一堆报错,我挨个分析。

四 漫长的修正bug之路

报错1,“netdb.h:No such file or directory”

1.报错:首先出现的报错如图,对应的libsnmp.cpp文件如图所示
在这里插入图片描述
2.分析:从报错位置来看,百度可知,这部分报错的可能原因,猜测是因为该部分头文件再windows中并不存在,是linux中的内容,不管是不是这个原因,可以确定的是,这几个头文件压根就不存在

3.解决:头文件不存在,那就不加载就行了,因此,做如下修改:
在这里插入图片描述

报错2,“‘in6_addr’was not declared in this scope”

1.报错:接着编译,锤子,然后出现新的问题,这次出现再address.cpp中。
在这里插入图片描述
2.分析:分析编译出错的部分的内容,可以猜测,这部分内容是与ipv6相关,关键词搜索宣称的不存在的内容,没找到定义的位置,因此想到,能不能直接不要这部分,因为其实现在我所接触的大部分时候,还用不着IPV6,因此干脆不要了。那如何能让他不编译,看见上面写着ifdef SNMP_PP_IPv6,意思是,如果定义了SNMP_PP_IPv6,就执行下面一部分内容,那直接不定义SNMP_PP_IPv6,不就行了?于是,全局搜索define SNMP_PP_IPv6,果然存在。
在这里插入图片描述
3.解决:将上图中的,红框内的内容,注释掉即可,问题解决

报错3,“openssl/des.h:No such file or directory”

1.报错:这次出问题的是auth_priv.cpp,分析其中内容
在这里插入图片描述
2.分析:由报错的内容分析,可以看出来,这一部分是用来加密用的,这个情况很明显,就是却一个des.h头文件,这个头文件很眼熟,没错,在刚刚下载的两个源代码中,解压了snmp++,而另一个libdes一直还没用上,里面就有一个des.h,那是不是复制过来就行?这并不能解决问题,因为可以看见,即便des.h找到了,后面两个人就不存在,因此,问题的根本在于,是否需要使用openssl,实际上是可以不用这个的。
3.解决:因此,根据ifdef _USE_OPENSSL可知,搜索define _USE_OPENSSL。如下图,注释掉红框内的内容即可。
在这里插入图片描述

报错4,“des.h:No such file or directory”

1.报错:上一步将openssl给禁用了,新的报错出现了。
在这里插入图片描述
2.分析:很明显,就是在将openssl禁用的情况下,这个snmp++有备选方案,备选方案,没错,就是使用libdes,即下载的两个文件,一个snmp++,一个libdes,刚仅仅使用了snmp++,这会将发挥libdes的作用了,在解压libdes后发现,里面有des.h文件。
3.解决:libdes文件夹下,有多个头文件和cpp文件,不晓得需不需要将别的也复制过来,但是,既然报错是des.h文件,那就先解决眼下的问题。复制过来后,编译,这个问题解决了。

报错5,“undefined reference to ‘_imp_htonl’”

报错:这只是第一条,出现的不仅仅这条报错。
在这里插入图片描述
2.分析:上网百度可以发现,缺失的内容都是一个叫ws2_32的库文件,这是提供了对部分网络相关API的支持的,这个库系统中会自带,因此,只需要引入即可。
3.解决:在.pro文件中添加 LIBS += -lws2_32,问题解决。
在这里插入图片描述

报错6,“undefined reference to ‘des_key_sched’”

1.报错:又出现新的报错。
在这里插入图片描述
2.分析:undefined,意思肯定是缺少了一些库文件或者什么内容的调用。再观察到缺少的东西的名字,里面有一个des的字眼,猜测估计就是缺少了libdes文件夹下的内容

3.解决:不知道缺的是哪个,一不做二不休,把libdes下的所有.h和.c都复制过来,编译,问题果然解决。
在这里插入图片描述

五 编译结果

1.查看编译生成的内容
在这里插入图片描述
图中点选即生成的内容,.a和.dll库文件,即开发所需的.a文件,和运行过程中需要的.dll文件。

六 注意事项

1.一定要搞清楚头文件和cpp文件等存放的位置,报错各个头文件的拓扑关系,这在后续的库文件的使用中,尤其重要。

2.编译过程中,缺什么别慌,冷静分析,看能不能找不到,同时也得注意看代码,分析是否可以跳过该部分内容。

3.注意关注点,生成库文件的工程文件,比如我所用的例子中的,snmp_dev.h和snmp_dev.cpp文件,一定记得删除cpp文件,然后在.h文件中,将原来的内容全清空了,主要指的是原有的class等内容,只需要引入#include snmp/snmp_pp.h即可。如原有的class等内容不清空,编译中虽然不报错,但是编译出的.a文件就是空文件,无法使用。

4.编译结果的.a和.dll文件,区别在于.a是程序编译生成所需,.dll是程序运行所需的。

七 运用编译的库

1搞清楚我们有什么库文件以及放在哪
动态库文件。有两个,一个是snmp_dev.a,一个是snmp_dev.dll,以及相应的头文件。我们将这两个库文件放在同一个文件夹下,比如创建一个名为lib的文件夹。将该文件夹放置在需调用snmp功能的工程文件的目录下。同时,创建一个名为include的文件夹,将头文件放进该文件夹下,将include文件夹也放置在该工程目录下。snmp_dev.a是为了编译使用,snmp_dev.dll是为了程序运行使用,没有.dll库文件,exe文件无法运行。因此在发布时,需要将snmp_dev.dll文件复制到与exe同个目录下。
在这里插入图片描述
include的文件夹下的文件
在这里插入图片描述
lib文件夹下面的文件
在这里插入图片描述
2 库文件及头文件的导入
在这里插入图片描述
3.选择 外部库
在这里插入图片描述
4.动态库的导入如下选择,勾选动态
在这里插入图片描述

五 测试代码

服务器的代码

#include <QCoreApplication>
#include<snmp_dev.h>
#include<snmp_pp/snmp_pp.h>
#include<snmp_pp/oid.h>
#include <winsock2.h>

using namespace  std;
using namespace  Snmp_pp;


//#pragma comment(lib, "ws2_32.lib")

#define SYSDESCR      "1.3.6.1.2.1.1.1.0"        //ObjectID for system descriptor
#define SYSOBJECTID   "1.3.6.1.2.1.1.2.0"        //ObjectID for system object ID
#define SYSCONTACT    "1.3.6.1.2.1.1.4.0"        //ObjectID for system contact
#define coldStart     "1.3.6.1.6.3.1.1.5.1"
#define ZYX1          "1.3.6.1.2.1.1.1.1"
#define ZYX2          "1.3.6.1.2.1.1.1.2"
#define ZYX3          "1.3.6.1.2.1.1.1.101"
using namespace  std;
using namespace  Snmp_pp;


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Snmp::socket_startup();  //初始化socket子系统

    int status;
    Vb vb[3];
    Pdu pdu;
    vb[0].set_oid(SYSDESCR);
    vb[1].set_oid(ZYX1);
    vb[2].set_oid(ZYX3);
    pdu.set_vblist(vb,3);
    CTarget ctarget((IpAddress) "127.0.0.1");  //被管代理的ip
    Snmp snmp(status);
    if((status=snmp.get(pdu, ctarget))!=SNMP_CLASS_SUCCESS)
    {
        cout<<snmp.error_msg(status);
    }
    else
    {
        pdu.get_vblist(vb,3);
        for(int i=0;i<3;i++)
        {
            cout<<"oid:"<<vb[i].get_printable_oid()<<" "<<"value:"<<vb[i].get_printable_value()<<endl;
        }

    }

    return a.exec();
}

代理的代码

#include <QCoreApplication>
#include "agent_dev.h"
#include "agent_dev_global.h"
#include<snmp_pp/snmp_pp.h>
#include<agent_pp/agent++.h>
#include<agent_pp/mib.h>
#include<agent_pp/mib_entry.h>
#include<agent_pp/request.h>
#include<QDebug>
#include<agent_pp/snmp_group.h>
#include<agent_pp/system_group.h>
#include <agent_pp/snmp_target_mib.h>
#include <agent_pp/snmp_notification_mib.h>
#include"qagent.h"
using namespace std;
using namespace  Snmp_pp;
using namespace Agentpp;

#define SYSDESCR      "1.3.6.1.2.1.1.1.0"        //ObjectID for system descriptor
#define SYSOBJECTID   "1.3.6.1.2.1.1.2.0"        //ObjectID for system object ID
#define SYSCONTACT    "1.3.6.1.2.1.1.4.0"        //ObjectID for system contact
#define coldStart     "1.3.6.1.6.3.1.1.5.1"
#define ZYX1          "1.3.6.1.2.1.1.1"
#define ZYX2          "1.3.6.1.2.1.1.2"
#define ZYX3          "1.3.6.1.2.1.1.101"
bool run = true;
static void sig(int signo)
{
    if ((signo == SIGTERM) || (signo == SIGINT) ||(signo == SIGSEGV))
    {
        printf ("\n");
        switch (signo)
        {
        case SIGSEGV:
        {
            qDebug()<<"Segmentation fault, aborting.";
            exit(1);
        }
        case SIGTERM:
        case SIGINT:
        {
            if (run)
            {
                qDebug()<<"User abort";
                run = false;
            }
        }
        }
    }
}

void init_signals()
{
    signal (SIGTERM, sig);
    signal (SIGINT, sig);
    signal (SIGSEGV, sig);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Snmp::socket_startup();
    int status;
    unsigned short port = 161; //161为监听端口 162为Trap端口
    UdpAddress address("127.0.0.1");
     address.set_port(port);
    Snmpx snmp(status,address);
    if( SNMP_CLASS_SUCCESS == status)
    {
       Mib mib;
       //将oid 和对应的value放入这个Mib里面,等请求到到来的时候 代理会在这个Mib里面查询相应的信息来处理
       mib.add(new snmpGroup());
       mib.add(new snmp_target_mib());
       mib.add(new snmp_notification_mib());
       mib.add(new MibLeaf("1.3.6.1.2.1.1.1.0", READONLY, new OctetStr("SYSDESCR")));
       mib.add(new MibLeaf("1.3.6.1.2.1.1.1.1", READONLY, new OctetStr("zyx1")));
       mib.add(new MibLeaf("1.3.6.1.2.1.1.1.2", READONLY, new OctetStr("zyx2")));
       mib.add(new MibLeaf("1.3.6.1.2.1.1.1.101", READWRITE, new OctetStr("zyx3")));

        //创建RequestList
        RequestList* reqList = new RequestList(&mib);

        mib.set_request_list(reqList);

        init_signals();

        reqList->set_snmp(&snmp);

        mib.init(); //mib 初始化
        //监听循环 此处循环何时退出可根据实际情况来做修改
        Request* req;
        while (run)
        {
            req = reqList->receive(5);
            if (req)
            {
                mib.process_request(req);//对请求进行处理,请求包括get,getNext,getBulk,walk,set。
            }
            else
            {
                mib.cleanup();
            }
        }
        delete reqList;
        Snmp::socket_cleanup();
    }
    else
    {
        qDebug()<<"snmp port init failed!";
    }
    return a.exec();
}

我们先运行代理,开始监听请求,如下:
在这里插入图片描述
然后我们运行 服务器,发起get请求。
在这里插入图片描述
get之后获得得数据都打印了出来,oid和value对应。get时的iod一定是代理里面的Mib添加了的,存在的oid.

链接

接下来,我将对snmp里面的getgetNextgetBulksettrapinform这六种操作进行一一的讲解。
1.snm++操作之get
2.snmp++操作之getNext
3.snmp++操作之getBulk
4.snmp++操作之walk
5.snmp++操作之set
6.snmp++操作之trap
7.snmp++操作之阻塞式inform
8.snm++操作之异步inform

相关推荐

  1. 【Qt】QtCreator交叉编译环境配置Qt mkspec

    2024-07-19 21:52:05       40 阅读
  2. qtcreator msvc编译器 链接外部库的方式

    2024-07-19 21:52:05       36 阅读
  3. Go 跨平台编译

    2024-07-19 21:52:05       58 阅读
  4. codeArts Snap:辅助你的编程神器

    2024-07-19 21:52:05       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 21:52:05       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 21:52:05       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 21:52:05       57 阅读
  4. Python语言-面向对象

    2024-07-19 21:52:05       68 阅读

热门阅读

  1. CCF-CSP认证考试 202406-4 货物调度 100分题解

    2024-07-19 21:52:05       22 阅读
  2. 白骑士的PyCharm教学基础篇 1.1 PyCharm简介

    2024-07-19 21:52:05       18 阅读
  3. 从零开始学习嵌入式----数据结构

    2024-07-19 21:52:05       19 阅读
  4. 【笔记-软考】软件架构风格

    2024-07-19 21:52:05       21 阅读
  5. 小一保姆级 python函数基础详解

    2024-07-19 21:52:05       20 阅读
  6. 每天一个数据分析题(四百三十五)- 统计分析

    2024-07-19 21:52:05       18 阅读