snmp++ Trap实现

为了让程序更好地工作,需要解决进程阻塞问题,因为程序阻塞后,将一直等待Trap的到来,在没有接收到Trap前,程序将不响应任何消息。这对我们来说是不能忍受的。解决的办法是采用多线程技术,即开始接收trap时,启动另一个线程专门用来接收trap,而程序界面不至于被“冻结”。

启动与关闭trap监听

void CSnmpMgrDlg::OnTrap() //onTrap是按钮的相应处理

{

      CButton *pBt;

      pBt=(CButton *)GetDlgItem(IDC_TRAP);

      if(m_bRecvTrap==false)

      {

             if(pSnmp.sessionID==FALSE)  

             {

                    pSnmp.CreateSession(CSnmpMgrDlg::m_hWnd,wMsg);

                    pSnmp.sessionID=TRUE;

             }     

             m_bRecvTrap=true;

      AfxBeginThread(WorkerThreadProc,this,THREAD_PRIORITY_NORMAL,0,0,NULL);           ///创建线程, 线程函数为WorkerThreadProc 参数为this指针。

             pBt->SetWindowText("停止接收陷阱");              //修改按钮文字

      }

      else

      {

             m_bRecvTrap=false;

             Snmp::socket_startup();  

             UdpAddress address("127.0.0.1:162");      

             int status;

             Snmp snmp(status, 0) ;

             Pdu pdu;                               

             pdu.set_notify_id("1.3.6.1");               

             pdu.set_notify_enterprise( "test");

             CTarget ctarget(address);             

             ctarget.set_version( version1);        

             ctarget.set_readcommunity("public");

             SnmpTarget *target=&ctarget;

             status = snmp.trap(pdu,*target);        //向本机发送Trap以标志退出监听。

             Snmp::socket_cleanup();

             pBt->SetWindowText("开始接收陷阱");

      }

}

线程函数的实现。线程函数是一个全局函数。

UINT WorkerThreadProc(LPVOID Param)

{

      CSnmpMgrDlg *pCV;

      pCV=(CSnmpMgrDlg *)Param;       //将指针类型转换为CSnmpMgrDlg *类型指针;

      int trap_port=162;      //指定监听端口号;

      OidCollection oidc;

      TargetCollection targetc;   //创建过滤TRAP的对象;

      CNotifyEventQueue::set_listen_port(trap_port);     //设置端口号;

      int status;

      Snmp::socket_startup();  

      Snmp *snmp = new Snmp(status, 0);       // 创建Snmp对象;

      if ( status != SNMP_CLASS_SUCCESS)

      {

             AfxMessageBox("出现错误!");

             return TRUE;

      }

      status=snmp->notify_register(oidc, targetc,callme,Param);

      if (status != SNMP_CLASS_SUCCESS)

      {

             AfxMessageBox("出现错误!");

             return TRUE;

      }

      while(pCV->m_bRecvTrap)

             snmp->eventListHolder->SNMPProcessEvents();//进入SNMPProcessEvents()函数,等待TRAP触发回调用函数;

      Snmp::socket_cleanup();  

      AfxMessageBox("已停止!");

      return TRUE;

}

回调函数,用来处理接收到的trap

void callme (int reason, Snmp *snmp, Pdu &pdu, SnmpTarget &target, void *cd)

{  

    CString str="";

      CTime time=CTime::GetCurrentTime();

      CString time_str=time.Format("%Y-%m-%d:%H:%M:%S");  //计算接收的时间

      CSnmpMgrDlg *p;

      p=(CSnmpMgrDlg *)cd;

      Vb nextVb;

      GenAddress addr;

      target.get_address(addr);

      IpAddress from(addr);

      CString ipadd=from.get_printable();                //获取ip地址

      if (ipadd=="127.0.0.1")

             return;    //结束监听时本机发送的TRAP退出循环,不做任何处理;

      Oid id,ent;

      pdu.get_notify_id(id);

      pdu.get_notify_enterprise(ent);

      CString TrapId=id.get_printable();            //获取Trap id

      CString EnterPrise=ent.get_printable();           //获取 Enterprise

      CString index,name;

      pdu.get_vb(nextVb, 0);

      index=nextVb.get_printable_value();               //获取被管对象索引值

    pdu.get_vb(nextVb, 1);

    name=nextVb.get_printable_value();                    //获取被管对象名称

///此处处理并显示给用户数据

      }

你可能感兴趣的:(snmp++ Trap实现)