Qt 使用 net-snmp 包的过程记录
使用 C/C++ 进行 SNMP 开发,网上比较流行的主要是用 net-snmp 和 snmp++ 。在 sourceforge 上以 Qt 和 snmp 为关键词进行搜索,搜到的项目 net-snmp 相关的占了多数,推测,net-snmp 的使用人数可能更多一点。遂决定采用 net-snmp。
仍然是从 sourceforge 开始,随便找了一个规模不大的项目,开始对 net-snmp 进行熟悉。
1. 尝试代码编译
从项目把代码拉过来: git clone https://git.code.sf.net/p/qt-snmp/code qt-snmp-code
文件里没有 project 文件,使用 qt -project 生成 source.pro,qmake,make。
遇到没有 net-snmp-config.h 头文件的问题,很明显,是因为 net-snmp 库没有安装。
2. 安装 libnetsnmp
首先,因为这个代码库看起来比较早,所以选择了一个比较早期的 net-snmp 版本(2011)。snmp 已经是非常成熟的协议,所以,并不担心比较早的版本协议实现不完整。
从 sourceforge 下载代码包 net-snmp-5.4.4.tar.gz,并解压,进入代码根目录。
因为 net-snmp 的部分实现严重依赖 perl,所以,需要先安装 perl 的开发包:
然后进行 configure , make , make install.
另外,net-snmp 还依赖 openssl。在这里花了比较长的时间。因为我的交叉编译器只有 openssl 头文件,并没有库文件,而且我编译 net-snmp 又是用的静态库,所以,链接的时候老是提示没有一些加密函数。下面是我重新编译 openssl 的 config 配置(用从 ubuntu 下 的 openssl098_0.9.8o.orig.tar.gz):
CC=arm-linux-gcc ./config no-asm --prefix=/tmp/openssl
为 arm 编译 net-snmp 库使用的 configure 选项:
../configure --host=arm-linux --target=arm-linux --build=i686-linux --disable-shared --disable-scripts -enable-mini-agent --disable-ipv6 --disable-manuals --disable-ucd-snmp-compatibility --enable-as-needed --with-endianness=little --prefix=/tmp/snmp/
3. 继续编译 demo 的代码
因为已经安装了 libnetsnmp,而且代码要用到这个包,所以需要修改 project 文件,添加:
LIBS +=-lnetsnmp
make,成功。
暂时没有测试的环境,不知道程序是否有效,暂时先阅读一下代码。
4. 阅读项目代码
读完代码发现,真的只是写了一个最基本的 demo,界面倒是看起来做了一堆。甚至怀疑他这个最基本功能有没有实现,暂时没法测试,学习一下他的过程。
最主要业务代码,是在 snmpGet() 函数里,全文如下:
void MainWindow::SnmpGet() {
init_snmp("snmp get");
struct snmp_session sessionToPeer;
snmp_sess_init(&sessionToPeer); sessionToPeer.peername = strdup(agentDeviceAddressLineEdit->text().toStdString().c_str());
/*memory allocated by strdup() will be freed by calling snmp_close() */
if(snmpVersion1RadioButton->isChecked()) {/* snmp version 1 is obsolete, do nothing about it. */
}
if(snmpVersion2RadioButton->isChecked()) {/* only version 2 community is implemented here */
sessionToPeer.version = SNMP_VERSION_2c;
sessionToPeer.community = (u_char*) (strdup(communityLineEdit->text().toStdString().c_str()));
sessionToPeer.community_len = strlen((const char*) sessionToPeer.community);
}
if(snmpVersion3RadioButton->isChecked()) { //TODO: implement SNMP version 3 options. more item may be needed to add to combo box. }
sessionToPeer.retries = retriesSpinBox->value();
sessionToPeer.timeout = timeoutSpinBox->value();
SOCK_STARTUP;
struct snmp_session* sessionReturnedByLibrary = snmp_open(&sessionToPeer);
if(sessionReturnedByLibrary == NULL) {
#ifdef QT_DEBUG
snmp_sess_perror((const char*) "No Ack!", sessionReturnedByLibrary);
#endif //QT_DEBUG
SOCK_CLEANUP;
return;
}
struct snmp_pdu* requestPdu = snmp_pdu_create(SNMP_MSG_GET);
oid requestOid[MAX_OID_LEN];
size_t requestOidLength = MAX_OID_LEN;
snmp_parse_oid(".1.3.6.1.2.1.1.1.0", requestOid, &requestOidLength);
snmp_add_null_var(requestPdu, requestOid, requestOidLength);
struct snmp_pdu* responsePdu = NULL;
int snmpStatus = snmp_synch_response(sessionReturnedByLibrary, requestPdu, &responsePdu);
if(snmpStatus == STAT_SUCCESS and responsePdu->errstat == SNMP_ERR_NOERROR) {
/* SUCCESS: Print the result variables */
struct variable_list *snmpVariables;
#ifdef QT_DEBUG
for(snmpVariables = responsePdu->variables; snmpVariables; snmpVariables = snmpVariables->next_variable) {
print_variable(snmpVariables->name, snmpVariables->name_length, snmpVariables);
}
#endif //QT_DEBUG
/* retrieve response that we're interested. */
#ifdef QT_DEBUG
int count = ;
#endif //QT_DEBUG
for(snmpVariables = responsePdu->variables; snmpVariables != NULL; snmpVariables = snmpVariables->next_variable) {
if(snmpVariables->type == ASN_OCTET_STR) {
char* response = (char *) malloc( + snmpVariables->val_len);
memcpy(response, snmpVariables->val.string, snmpVariables->val_len);
response[snmpVariables->val_len] = '\0';
#ifdef QT_DEBUG
printf("value #%d is a string: %s\n", count++, response);
#endif //QT_DEBUG
resultTextEdit->setText(QString(response));
free(response);
} else {
#ifdef QT_DEBUG
printf("value #%d is NOT a string! Ack!\n", count++);
#endif //QT_DEBUG
}
}
} else {
/* FAILURE: print what goes wrong! */
#ifdef QT_DEBUG
if(snmpStatus == STAT_SUCCESS) {
fprintf(stderr, "Error in packet\nReason: %s\n", snmp_errstring(responsePdu->errstat));
} else if(snmpStatus == STAT_TIMEOUT) {
fprintf(stderr, "Timeout: No response from %s.\n", sessionToPeer.peername);
} else {
snmp_sess_perror("snmp get", sessionReturnedByLibrary);
}
#endif //QT_DEBUG
} /*
* Clean up:
* 1) free the response.
* 2) close the session.
*/
if(responsePdu) {
snmp_free_pdu(responsePdu);
}
snmp_close(sessionReturnedByLibrary); SOCK_CLEANUP;
}
大致步骤:
1) 对 snmp 协议栈进行初始化,init_snmp();
2) 新建 snmp 会话,对 session 进行初始化, 并对 session 进行基本的设置,比如 session 使用的协议、session 的重试次数以及等待时间等;
3) 使用 snmp_create_pdu( MSG_TYPE) 来组装 request_pdu。查看这个版本的协议,支持的 pdu 类型有:
/*
* PDU types in SNMPv1, SNMPsec, SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3
*/
#define SNMP_MSG_GET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x0) /* a0=160 */
#define SNMP_MSG_GETNEXT (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x1) /* a1=161 */
#define SNMP_MSG_RESPONSE (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x2) /* a2=162 */
#define SNMP_MSG_SET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x3) /* a3=163 */ /*
* PDU types in SNMPv1 and SNMPsec
*/
#define SNMP_MSG_TRAP (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x4) /* a4=164 */ / * PDU types in SNMPv2p, SNMPv2c, SNMPv2u, SNMPv2*, and SNMPv3 */
#define SNMP_MSG_GETBULK (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x5) /* a5=165 */
#define SNMP_MSG_INFORM (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x6) /* a6=166 */
#define SNMP_MSG_TRAP2 (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x7) /* a7=167 */ /*
* PDU types in SNMPv2u, SNMPv2*, and SNMPv3
*/
#define SNMP_MSG_REPORT (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x8) /* a8=168 */
为 request_pdu 指定 oid(这里指定固定的 oid,mib 文件并没有使用)。
4) 使用 nmp_synch_response(sessionReturnedByLibrary, requestPdu, &responsePdu) 来出发请求,并获取 resopose_pdu.
5) 当正确的获取 response_pdu 之后,在一个 for 循环中历遍 response_pdu 中的 netsnmp_variable_list,将所有 variables 的 value 都按照字符串打印出来。
6) 到所有的最后,关闭 session,删除 pdu。
以上,完成了一个基本的 snmp_get 请求。
Qt 使用 net-snmp 包的过程记录的更多相关文章
- openWRT自学---自己编译的第一个 backfire10.03 版本的过程记录 --- 实际是由于下载了错误的backfire源码包导致的
基于 backfire10.03(从http://downloads.openwrt.org/backfire/10.03/ 中下砸的源码包backfire_10.03_source.tar.bz2: ...
- qt之fillder抓包(QT网络版有一些具体的坑)
最近项目中使用到了Qt的网络库,在用的过程中也发现了不少坑和问题,本文仅仅作为记录,方便日后查阅. 因为我们整个客户端的gui都是使用qt来完成的,心想qt既然有网络库,而且真心觉着qt封装的控 ...
- qt之fiddler抓包
最近项目中使用到了Qt的网络库,在用的过程中也发现了不少坑和问题,本文仅仅作为记录,方便日后查阅. 因为我们整个客户端的gui都是使用qt来完成的,心想qt既然有网络库,而且真心觉着qt封装的控 ...
- CentOS 5.5 下安装Countly Web Server过程记录
CentOS 5.5 下安装Countly Web Server过程记录 1. 系统更新与中文语言包安装 2. 基本环境配置: 2.1. NodeJS安装 依赖项安装 yum -y install g ...
- 【转】android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创)
原文网址:http://www.cnblogs.com/zdz8207/archive/2012/11/27/android-ndk-install.html android 最新 NDK r8 在w ...
- 升级到 ExtJS 5的过程记录
升级到 ExtJS 5的过程记录 最近为公司的一个项目创建了一个 ExtJS 5 的分支,顺便记录一下升级到 ExtJS 5 所遇到的问题以及填掉的坑.由于 Sencha Cmd 的 sencha ...
- openWRT自学---自己编译的第一个 backfire10.03 版本的过程记录(转)
基于 backfire10.03(从http://downloads.openwrt.org/backfire/10.03/ 中下砸的源码包backfire_10.03_source.tar.bz2: ...
- 菜鸟如何使用hanlp做分词的过程记录
菜鸟如何使用hanlp做分词的过程记录 最近在学习hanlp的内容,准备在节后看看有没有时间整理一波hanlp分享下,应该还是会像之前分享DKHadoop一样的方式吧.把整个学习的过程中截图在配文字的 ...
- 将React Native 集成进现有OC项目中(过程记录) 、jsCodeLocation 生成方式总结
将RN集成到现有OC项目应该是最常见的,特别是已经有OC项目的,不太可能会去专门搞个纯RN的项目.又因为RN不同版本,引用的依赖可能不尽相同,所以特别说明下,本文参考的文档是React Native ...
随机推荐
- 关于 java,nio,bufferedreader,bytebuffer
有没有一种方法来读取的ByteBuffer有一个BufferedReader,而无需将其转换为String优先?我想读通过一个相当大的 ByteBuffer作为文本行和我想避免它写入磁盘性能方面的原因 ...
- SharePoint Online 创建网站集
前言 本文介绍如何在Office 365中创建SharePoint网站集. 正文 通过登录地址登录到Office 365环境中,我们可以在左上角的按钮中点开,进入管理员,也可以直接在页面中点击管理: ...
- left join 注意事项
相信对于熟悉SQL的人来说,LEFT JOIN非常简单,采用的时候也很多,但是有个问题还是需要注意一下.假如一个主表M有多个从表的话A B C …..的话,并且每个表都有筛选条件,那么把筛选条件放到哪 ...
- 逍遥法外第一季/全集How To Get Away With Murder迅雷下载
英文译名 How To Get Away With Murder (第1季) (2014-09-26首播)ABC.本季看点: <逍遥法外又名:天才刑法班>由<实习医生格蕾>和& ...
- Universal-Image-Loader解析(三)——用ListView和ViewPager加载网络中的图片
现在我们终于可以通过这个框架来实现ListView中加载图片了,至于ViewPager还是别的,原理其实都是一样的 一.ListView 1.布局文件 list_layout.xml & ...
- Mysql 的子查询
子查询: 子查询:嵌套在其它查询中的查询语句.(又称为内部查询) 主查询:包含其它子查询的查询称为主查询.(又称外部查询) 非相关子查询: 在主查询中,子查询只需要执行一次,子查询结果不再变化,供主查 ...
- [Web 前端] Jquery实现可直接编辑的表格
cp from :https://www.cnblogs.com/sjqq/p/6392001.html?utm_source=itdadao&utm_medium=referral 文实例讲 ...
- dubbo源码解析-spi(3)
前言 在上一篇的末尾,我们提到了dubbo的spi中增加了IoC和AOP的功能.那么本篇就讲一下这个增加的IoC,spi部分预计会有四篇,因为这东西实在是太重要了.温故而知新,我们先来回顾一下,我们之 ...
- Binary Tree ZigZag Level Order Traversal leetcode java
题目: Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from lef ...
- Palindrome Number leetcode java
题目: Determine whether an integer is a palindrome. Do this without extra space. click to show spoiler ...