前言
由于工作需要,封装打印机SDK,该篇主要讲解如何获取打印机的状态,打印机支持简单网络管理协议(SNMP),并且windows api支持snmp通讯协议;所以,就使用snmp协议查询打印机状态
一、SNMP协议简介
简单网络管理协议(SNMP),是TCP/IP协议簇的一个应用层协议,工作在UDP 161端口,用于监控目标设备的操作系统、硬件设备、服务应用、软硬件配置、网络协议状态、设备性能及资源利用率、设备报错事件信息、应用程序状态等软硬件信息。已经有3个版本,SNMPv1、SNMPv2、SNMPv3,我打印机使用的是SNMPv2。
SNMP常见的请求类型有Get、GetNext、Set和Trap等等,用来在管理进程和代理之间的通讯。
二、对象标识符OID
OID是SNMP代理提供的具有唯一标识的键值,它是一种分级树的结构,格式类似于1.3.6.1.2.1.4.3这种写法
,每个OID都有不同的功能,通过SNMP请求可返回相应结果
三、SNMP接口描述
1、SnmpMgrOpen(),初始化通信套接字和数据结构,允许与指定的SNMP代理进行通信。
LPSNMP_MGR_SESSION SNMP_FUNC_TYPE SnmpMgrOpen(
LPSTR lpAgentAddress,
LPSTR lpAgentCommunity,
IN INT nTimeOut,
IN INT nRetries
);
2、SnmpMgrClose(),闭与指定会话关联的通信套接字和数据结构
BOOL SNMP_FUNC_TYPE SnmpMgrClose(
IN LPSNMP_MGR_SESSION session
);
3、SnmpMgrStrToOid();将对象标识符的字符串格式转换为其内部对象标识符结构
BOOL SNMP_FUNC_TYPE SnmpMgrStrToOid(
LPSTR string,
OUT AsnObjectIdentifier *oid
);
4、SnmpUtilMemAlloc(), 为SnmpVarBind结构分配内存。
LPVOID SNMP_FUNC_TYPE SnmpUtilMemAlloc(
UINT nBytes
);
5、SnmpUtilVarBindListFree(), 释放为SnmpVarBindList结构分配的内存。
VOID SNMP_FUNC_TYPE SnmpUtilVarBindListFree(
SnmpVarBindList *pVbl
);
6、SnmpMgrRequest(); 请求使用指定的代理执行指定的操作,Get、GetNext、Set等请求
SNMPAPI SNMP_FUNC_TYPE SnmpMgrRequest(
IN LPSNMP_MGR_SESSION session,
IN BYTE requestType,
IN OUT RFC1157VarBindList *variableBindings,
OUT AsnInteger *errorStatus,
OUT AsnInteger *errorIndex
);
代码如下(示例):
#include <Snmp.h>
#include <MgmtAPI.h>
#pragma comment(lib, "Snmpapi.lib")
#pragma comment(lib, "Mgmtapi.lib")
char g_szIpAddress[MAX_PATH] = "192.168.1.1";
int GetOIDInteger(char* oid, int *outIngeger)
{
if (oid == NULL || outIngeger == NULL)
{
return 1;
}
// oid(对象标识符)
AsnObjectIdentifier aoidStatus;
char oidValue[64] = { 0 };
memcpy(oidValue, oid, strlen(oid));
// 将字符串格式的oid转换成内部oid对象标识符
if (!SnmpMgrStrToOid(oidValue, &aoidStatus))
{
// 无效oid
return 2;
}
// 初始化通信套接字和数据结构,获取会话句柄
LPSNMP_MGR_SESSION lpSession = SnmpMgrOpen(g_szIpAddress, "public", 2000, 3);
if (lpSession == NULL)
{
return 3;
}
int iRet = 0;
AsnInteger errStatus;
AsnInteger errIndex;
// 绑定SNMP变量
SnmpVarBindList svbList;
svbList.len = 1;
svbList.list = (SnmpVarBind *)SnmpUtilMemAlloc(sizeof(SnmpVarBind) * svbList.len);
svbList.list->name.idLength = aoidStatus.idLength;
svbList.list->name.ids = aoidStatus.ids;
// 请求返回的数据类型,ASN_INTEGER是整型,ASN_OCTETSTRING是字符串
svbList.list->value.asnType = ASN_INTEGER;
SNMPAPI snmpRet = SnmpMgrRequest(lpSession, SNMP_PDU_GET, &svbList, &errStatus, &errIndex);
if (snmpRet == NULL)
{
// 释放资源
SnmpUtilVarBindListFree(&svbList);
SnmpMgrClose(lpSession);
return 4;
}
if (errStatus == SNMP_ERRORSTATUS_NOERROR)
{
// 请求的类型和返回的类型一致
if (svbList.list->value.asnType == ASN_INTEGER)
{
*outIngeger = svbList.list->value.asnValue.number;
iRet = 0;
}
else
{
iRet = 5;
}
}
else
{
iRet = 6;
}
// 释放资源
SnmpUtilVarBindListFree(&svbList);
SnmpMgrClose(lpSession);
return iRet;
}
示例里面只描述了Get请求类型,其他请求类型差不多,只是参数设置不一样,就不再叙述了。