該程式摘自《深入了解NET-SNMP實戰》第8章的示例程式,編譯本書代碼的前提是已經從NET-SNMP源碼編譯出lib檔案。
同僚有完整的源代碼檔案。
一、程式源代碼
#include<net-snmp/net-snmp-config.h>
#include<net-snmp/includes.h>
#include<string.h>
int main(int argc,char *argv)
{
/*
結構體netsnmp_session中記錄了SNMP會話資訊;
第一個變量需要填充準備會話的資訊,
第二個為一指針用于記錄傳回的會話資訊;
*/
netsnmp_session session,*ss;
netsnmp_pdu *pdu;//該結構體中記錄了遠端主機所有的資訊。
netsnmp_pdu *response;//該結構體中記錄了遠端主機傳回的PDU資訊。
//記錄OID節點位置資訊
oid anOID[MAX_OID_LEN];
size_t anOID_len;
//變量綁定清單(為list資料結構),也就是需要操作的資料。
netsnmp_variable_list *vars;
int status;
int count=1;
/*
初始化SNMP庫;
初始化互斥量、MIB解析、傳輸層、
調試資訊的初始化、解析配置檔案的初始化(netsnmp_ds_register_config),各種句柄的初始化。
定時器的初始化、讀取配置檔案
*/
init_snmp("snmpdemoapp");
/*
session的初始化:包括初始化目的地,SNMP協定版本、認證機制、初始化會話結構體(為預設值),不是及任何的MIB檔案處理。
*/
snmp_sess_init(&session);
//設定會話結構體:目标位址;可以為其他有效的網絡位址
session.peername=strdup("localhost");
//使用SNMPv1版本
session.version=SNMP_VERSION_1;
//設定共同體
session.community="public";
session.community_len=strlen(session.community);
/*
開啟和綁定底層的傳輸層(TCP/UDP),建立會話,傳回會話句柄,每個會話對應一個socket
*/
ss=snmp_open(&session);
if(!ss){
snmp_sess_perror("snmpdemoapp",&session);
exit(1);
}
/* 會話建立完成後,接下來是建立指定類型(指令類型)的PDU,作為本次會話的執行個體執行操作的準備,
這就包括綁定準備通信的OID
*/
pdu=snmp_pdu_create(SNMP_MSG_GET);
anOID_len=MAX_OID_LEN;//該宏值為128,正如RFC建議所述“節點下子OID數量不超過128個”。
/*
此處read_objid / snmp_parse_oid的作用是檢查OID的正确性,
兵賦予anOID正确的值,也就是最終請求的OID
*/
//read_objid("system.sysDescr.0", anOID, &anOID_len);
//if ( !snmp_parse_oid(".1.3.6.1.2.1.1.1.0",anOID, &anO_len)){
if(!snmp_parse_oid("system.sysDescr.0",anOID,&anOID_len)){
snmp_perror(".1.3.6.1.2.1.1.1.0");
exit(1);
}
/*
按照協定PDU格式的要求,将該OID加入到PDU封包中,
同時賦予一個NULL值作為變量的綁定;
當然對于SET指令的PDU來說就是賦予待設定的值。
*/
snmp_add_null_var(pdu,anOID,anOID_len);
//同步發送封包。
status = snmp_synch_response(ss,pdu,&response);
/*
下面的代碼是處理傳回的PDU封包,需要根據傳回的資訊作出合理的後續處理:
封包的傳回和執行狀态都正确,讀取傳回的值。
*/
if( status == STAT_SUCCESS && response->errstat ==SNMP_ERR_NOERROR){
//将讀取的傳回值列印到标準輸出(stdout)出來。
for(vars=response->variables;vars;vars=vars->next_variable)
print_variable( vars->name, vars->name_length,vars );//處理(列印)接收到的資訊;
for(vars=response->variables;vars;vars=vars->next_variable)
{
if(vars->type==ASN_OCTET_STR){
char *sp = (char *)malloc(1 + vars->val_len);
memcpy(sp,vars->val.string,vars->val_len);
sp[vars->val_len]='\0';
printf("value #%d is a string :%s\n", count++,sp);
free(sp);
}else{
//如果傳回值有錯誤:列印其錯誤資訊
printf("value #%d is NOT a string! Ack\n",count++);
}
}
}else{
if(status == STAT_SUCCESS)
fprintf(stderr,"Error in packet\nReason: %s\n",snmp_errstring(response->errstat));
else if(status == STAT_TIMEOUT)
fprintf(stderr,"Timeout: No response from %s. \n",session.peername);
else
snmp_sess_perror("snmpdemoapp",ss);
}
//釋放配置設定的空間:關閉會話,關閉socket,釋放資源。
if(response)
snmp_free_pdu(response);
snmp_close(ss);
return(0);
}
二、程式編譯的環境
1.IDE: VisualStudio2010
2. SNMP庫版本:net-snmp 5.7.3
3.建立Win32控制台空項目(選擇預先編譯頭檔案)
4.建立CPP源檔案并拷貝以上源檔案。
三、編譯過程産生的問題。
問題一:找不到頭檔案和netsnmp_session。
解決方法:
1.添加頭檔案目錄(C/C++ | 正常 | 附加包含目錄 )
net-snmp-5.7.3 \ win32
net-snmp-5.7.3 \ include
2.修改原本包含的頭檔案(因為對應的版本檔案名改變了)
将#include <net-snmp/ includes.h >修改為 #include< net-snmp / net-snmp-includes.h >
問題二:error C2440: “=”: 無法從“const char [7]”轉換為“u_char *”
解決方法:
将
session.community="public";
session.community_len=strlen(session.community);
修改為:
session.community=(u_char *)"public";
session.community_len=strlen( (char*) session.community);
問題三:fatal error LNK1120: 13 個無法解析的外部指令
fatal error LNK1120: 26 個無法解析的外部指令
解決方法:
1.添加庫目錄(連結器 | 正常 | 附加庫目錄)
目錄選擇生成的連結庫所在的目錄。
2.添加連結庫檔案(以下使用宏處理指令方式添加)
#pragma comment (lib,"netsnmp.lib")
#pragma comment (lib, "ws2_32.lib")
第一個庫針對13個無法解析的指令。
第二個庫針對26個無法解析的指令。