Chinaunix首页 | 论坛 | 博客
  • 博客访问: 77398
  • 博文数量: 32
  • 博客积分: 1440
  • 博客等级: 上尉
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-25 16:03
文章分类

全部博文(32)

文章存档

2010年(12)

2008年(20)

我的朋友

分类: C/C++

2008-07-21 20:44:13

异步manager实现
一,        基本步骤
初始化部分
1,init_snmp初始化snmp
2,snmp_parse_oid根据mib分析parse oid
循环执行3-7,直到所有pdu都发出去
3,snmp_sess_init初始化session,然后用一些赋值语句设置session
4,设置session中的回调函数(callback),这个函数负责处理返回的信息
5,snmp_open打开session
6,snmp_pdu_create创建pdu
7,snmp_send发送包
循环执行8-10,直到没有active hosts
8,snmp_select_info设置多路复用的几个信息
9,select多路复用
10,snmp_read接受所有返回信息,具体处理交给callback
11,回调函数(callback),具体处理返回信息,参数是固定的,参数是:
int operation, struct snmp_session *sp, int reqid,struct snmp_pdu *pdu, void *magic
根据这些可以处理返回信息
二,        代码全注释
参照
更改了一些代码,read_objid改为snmp_parse_oid,更改了host中的name
删除了同步代码,和windows相关部分
#include
#include
/*
* a list of hosts to query
*/
Host结构
struct host {
  const char *name;
  const char *community;
} hosts[] = {
  { "192.168.213.116",                "public" },
  { "192.168.213.64",                "public" },
  { "192.168.213.116",                "public" },
  { "192.168.213.64",                "public" },
  { NULL }
};
/* a list of variables to query for*/
Oid结构
struct oid {
  const char *Name;
  oid Oid[MAX_OID_LEN];
  int OidLen;
} oids[] = {
  { "system.sysDescr.0" },
  { "interfaces.ifNumber.1" },
  { "interfaces.ifNumber.0" },
  { NULL }
};
/*
* initialize
*/
初始化函数
void initialize (void)
{
  struct oid *op = oids;
    /* Win32: init winsock */
  SOCK_STARTUP;
  /* initialize library */
初始化snmp库
  init_snmp("asynchapp");
  /* parse the oids */
根据mibs来parse oids
  while (op->Name) {
    op->OidLen = sizeof(op->Oid)/sizeof(op->Oid[0]);
    if (!snmp_parse_oid (op->Name, op->Oid, &op->OidLen)) {
      snmp_perror("read_objid");
      exit(1);
    }
    op++;指向oids数组的下一项
  }
}
/* simple printing of returned data*/
打印返回结果,这部分不是很重要,编写处理函数时候可以参考
int print_result (int status, struct snmp_session *sp, struct snmp_pdu *pdu)
{
  char buf[1024];
  struct variable_list *vp;
  int ix;
  struct timeval now;
  struct timezone tz;
  struct tm *tm;
  gettimeofday(&now, &tz);
  tm = localtime(&now.tv_sec);
  fprintf(stdout, "%.2d:%.2d:%.2d.%.6d ", tm->tm_hour, tm->tm_min, tm->tm_sec,
          now.tv_usec);
  switch (status) {
  case STAT_SUCCESS:
    vp = pdu->variables;
    if (pdu->errstat == SNMP_ERR_NOERROR) {
      while (vp) {
        snprint_variable(buf, sizeof(buf), vp->name, vp->name_length, vp);
        fprintf(stdout, "%s: %s\n", sp->peername, buf);
        vp = vp->next_variable;
      }
    }
    else {
      for (ix = 1; vp && ix != pdu->errindex; vp = vp->next_variable, ix++)
        ;
      if (vp) snprint_objid(buf, sizeof(buf), vp->name, vp->name_length);
      else strcpy(buf, "(none)");
      fprintf(stdout, "%s: %s: %s\n",
              sp->peername, buf, snmp_errstring(pdu->errstat));
    }
    return 1;
  case STAT_TIMEOUT:
    fprintf(stdout, "%s: Timeout\n", sp->peername);
    return 0;
  case STAT_ERROR:
    snmp_perror(sp->peername);
    return 0;
  }
  return 0;
}
/*
* poll all hosts in parallel
*/
struct session {
  struct snmp_session *sess;                /* SNMP session data */
  struct oid *current_oid;                /* How far in our poll are we */
} sessions[sizeof(hosts)/sizeof(hosts[0])];数量跟host一样多
active_hosts在asynch_response中减少,在asynchronous中增加
int active_hosts;                        /* hosts that we have not completed */
/*
* response handler
*/
int asynch_response(int operation, struct snmp_session *sp, int reqid,
                    struct snmp_pdu *pdu, void *magic)
{
  struct session *host = (struct session *)magic;
  struct snmp_pdu *req;
  if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
if (print_result(STAT_SUCCESS, host->sess, pdu)) {
每个host对应了3个oid,对每个都要发送包
asynchronous发送第一个包,这里对其他的oid发送包
      host->current_oid++;                        /* send next GET (if any) */
        下面的程序跟asynchronous中处理相同
      if (host->current_oid->Name) {
        req = snmp_pdu_create(SNMP_MSG_GET);
        snmp_add_null_var(req, host->current_oid->Oid, host->current_oid->OidLen);
        if (snmp_send(host->sess, req))
          return 1;
        else {
          snmp_perror("snmp_send");
          snmp_free_pdu(req);
        }
      }
    }
  }
  else
    print_result(STAT_TIMEOUT, host->sess, pdu);
  /* something went wrong (or end of variables)
   * this host not active any more
   */
  active_hosts--;处理完后,少了一个active host
  return 1;
}
void asynchronous(void)
{
  struct session *hs;
  struct host *hp;
  /* startup all hosts */
  for (hs = sessions, hp = hosts; hp->name; hs++, hp++) {
    struct snmp_pdu *req;
    struct snmp_session sess;
snmp_sess_init(&sess);        初始化session                /* initialize session */
设置session的各变量
    sess.version = SNMP_VERSION_2c;
    sess.peername = strdup(hp->name);
    sess.community = strdup(hp->community);
    sess.community_len = strlen(sess.community);
    sess.callback = asynch_response;设置回调函数                /* default callback */
sess.callback_magic = hs;回调函数的magic,传入打开的session
初始化和打开后返回的session不同
    if (!(hs->sess = snmp_open(&sess))) {
      snmp_perror("snmp_open");
      continue;
}
设置oid
hs->current_oid = oids;
创建pdu
    req = snmp_pdu_create(SNMP_MSG_GET);        /* send the first GET */
snmp_add_null_var(req, hs->current_oid->Oid, hs->current_oid->OidLen);
用异步方式发送包,不处理,等后面专门处理
    if (snmp_send(hs->sess, req))
      active_hosts++;增加一个活跃的host
    else {
      snmp_perror("snmp_send");
      snmp_free_pdu(req);
    }
  }
  /* loop while any active hosts */
  while (active_hosts) {只要有活跃的host就一直处理
    int fds = 0, block = 1;
    fd_set fdset;
    struct timeval timeout;
FD_ZERO(&fdset);把fd_set清零
Select具体应用请参考《unix网络编程》,或者internet高级编程讲义
设置select需要的信息
snmp_select_info(&fds, &fdset, &timeout, &block);
多路复用,直接这么用就行了
    fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
    if (fds name; hs++, hp++) {
    if (hs->sess) snmp_close(hs->sess);
  }
}
/*****************************************************************************/
int main (int argc, char **argv)
{
  initialize();
  printf("---------- asynchronous -----------\n");
  asynchronous();
  return 0;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/43391/showart_349801.html

阅读(626) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-01-08 23:32:33

您好 我也在学习snmp 有没有收trap的demo或者编程模式什么的 set get 都成功了,可是不知道如何收trap 希望得到你的帮助 zhaoforyou@gmail.com