论坛首页 综合技术论坛

SNMP管理端控制代理端小例子

浏览 5915 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-11-01   最后修改:2010-11-01

一个周末一直在进一步研究项目的管理端和代理端通信问题,早上终于有了点眉目,做个笔记。

 

实验的是一个远程控制代理端关机的功能。

 

管理端是用Java搭的前台网站,所以使用SNMP4J包编写程序。代理端使用agent++和snmp++两个开发包。

 

管理端的代码如下:

 

public static void main(String[] args) {
	Snmp snmp;
	try {
		//设置TransportMapping
		TransportMapping transport = new DefaultUdpTransportMapping();
		snmp = new Snmp(transport);
		transport.listen();
			
		//设置target
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString("public"));
		target.setAddress(GenericAddress.parse(("10.150.0.84/161"));
		target.setRetries(2);
		target.setTimeout(5000);
		target.setVersion(SnmpConstants.version1);
			
		//设置请求PDU
		PDU requestPDU = new PDU();		
		requestPDU.setType(PDU.SET);//设置PDU类型

		//设置Variable		 
		//Gauge32型 无符号长整型
		requestPDU.add(new VariableBinding(new OID("1.3.6.1.4.1.502.1.70"), new Gauge32(Integer.valueOf("1"))));
						
		//处理返回结果
		ResponseEvent respEvnt = snmp.send(requestPDU,target); //向Agent发送PDU,并接收Response	
   		PDU responsePDU = respEvnt.getResponse();//解析response	
	
      		if(responsePDU.getErrorIndex() == PDU.noError 
   			&& responsePDU.getErrorStatus() == PDU.noError) { 
			//如果接收包没有出错
   			String strResult = responsePDU.getVariableBindings().firstElement().toString();
   			int len = strResult.indexOf("=");
			strResult = strResult.substring(len+1, strResult.length()).trim();
			if(strResult.equals(value)){   //如果返回值与设置值相同,返回true,否则,返回false
				System.out.println("set操作成功!");
			}  else{
				System.out.println("set操作失败!oid值与设置值不同!");
			}  else{
				System.out.println("set操作失败,接收包有错误:"+responsePDU.getErrorStatusText());			
			}	
   	
			snmp.close();
		}
	} catch (Exception e) {
		e.printStackTrace();
	}	

}

 

 代理端比较复杂,主要代码如下:

 

//Subagent_Main.h

#include "StdAfx.h"
#include <windows.h>
#include <agent_pp/agent++.h>
#include <agent_pp/mib.h>
#include <agent_pp/mib_context.h>

#include <agentx_pp/agentx_subagent.h>

#define GROUP_OID "1.3.6.1.4.1.502.1"   //定义oid组
#define SHUTDOWN_OID "1.3.6.1.4.1.502.1.70"    //定义关机操作的oid

class Subagent_Main : public MibGroup {
public:
	Subagent_Main(const NS_SNMP OctetStr&, SubAgentXMib*);
	~Subagent_Main();

};

class Subagent_Shutdown : public MibLeaf {
public:
	Subagent_Shutdown();
	virtual ~Subagent_Shutdown();
	virtual int set(const Vbx&);
};

 

 实现:

 

//Subagent_Main.cpp
#include "stdafx.h"
#include "Subagent_Main.h"

Subagent_Main::Subagent_Main(const NS_SNMP OctetStr&, SubAgentXMib*) 
	:MibGroup(GROUP_OID, "Subagent") {
	add(new Subagent_Shutdown());
}

Subagent_Main::~Subagent_Main() {

}

Subagent_Shutdown::Subagent_Shutdown()
	 : MibLeaf(SHUTDOWN_OID, READWRITE, new Gauge32()) {
	
}

Subagent_Shutdown::~Subagent_Shutdown() {
		
}

Subagent_Shutdown::set(const Vbx& vb) {
	int isShutdown;
	vb.get_value(isShutdown);

	if(isShutdown) {
		//以下关机代码只对Win2000及以上版本系统有效

		HANDLE hToken;
		TOKEN_PRIVILEGES tkp;
		
		if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) {
			AfxMessageBox("无法打开存取命令");
			return 1;
		}
		
		LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
		tkp.PrivilegeCount=1;
		tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
		AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
		
		if(GetLastError()!=ERROR_SUCCESS) {
			AfxMessageBox("无法关机");
			return 1;
		}
		
		if(!ExitWindowsEx(EWX_POWEROFF|EWX_FORCE,0)) {
			AfxMessageBox("无法关机");
			return 1;
		}
		
	}
	
	return 0;
}

 测试函数内容如下:

 

先定义处理的线程函数Subagent:

 

UINT Subagent(LPVOID pPar) {
	//AfxMessageBox("子代理线程启动");

	SubAgentXMib* mib = new SubAgentXMib();

	AgentXSlave* agentx = new AgentXSlave();
	
	AgentXRequestList* reqList = new AgentXRequestList(agentx);

	// register requestList for outgoing requests
	mib->set_request_list(reqList);
	
	mib->add(new Subagent_Main("", mib)); //初始化
	
	mib->init();
	
	Request* req;

	while (TRUE) {	
		req = reqList->receive(20000);
		
		if (req) {
			mib->process_request(req);
		} else {
			mib->ping_master();  	// ping the master
		}
	}
	
	//AfxMessageBox("子代理线程结束");

	delete mib;
	delete agentx;

	return 0;
}

 

 最后在main函数里加入到开启线程函数即可:

 

AfxBeginThread(Subagent, NULL);   //开启子代理线程监听

 运行时,需要代理端装有snmp服务,但不能开启(一直不明白原因)。代理端先开启MasterAgent,再启动我们所写的代理Subagent。这时候管理端即可发控制请求。一运行,代理端即关机。

 

PS:大致流程如此,中间有很多细节需要慢慢调试。比如snmp++,agent++源码的下载,dll文件的编译生成等等。

下面仅附上SNMP4J开发包。

   发表时间:2010-11-20  
我放弃了 agent++,选用Net-Agent, 同样server端用snmp++ 多线程的api

效果比较好,不过发现两个问题

1 支持中文需要修改ans1源码
2 会把trap id 默认输出到debug
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics