CentOS/Ubuntu/Debian安装LibeventCentOS安装Libevent库(含示例代码)

0.在Linux系统上安装Libevent库

使用命令:CentOS安装Libevent库(含示例代码)

sudo yum install libevent-devel

 Ubuntu/Debian:

sudo apt install libevent-dev

1.什么是Libevent?

        理解Libevent之前首先理解信号,它是进程间通信的一种机制。它是一种软中断,用于宣布某种事件,比如我要中断一个进程,Linux信号默认以SIG开头,多达64种,具体各种信号及其默认操作与目的详见链接。在Linux上关于信号内容,请使用man 7 signal查看。

        其中有一个信号SIGINT,它的编号是2,通常在用户按下 `Ctrl+C `时被发送给前台进程,目的是中断它。

具体使用方法:

#include<signal.h>
#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
void my_handler(int sig){
  if(sig==SIGINT){
    cout<<"Received SIGINT."<<endl;
    exit(0);
  }
}
int main(){
  if(signal(SIGINT, my_handler)==SIG_ERR){//signal失败将返回SIG_ERR
    perror("signal");
    return 1;
  } // 我们使用signal()注册了信号处理函数:当程序收到SIGINT信号后调用my_handler();
  while (1){
    cout << "while(1)" << endl;
    sleep(2);
  }
}

        如上,我们使用signal注册了信号处理函数,在程序接收到SIGINT信号也就是2号信号后调用my_handler函数,打印并释放资源。 

        而Libevent作为C语言实现的网络库,他使得你可以在某个信号(比如SIGINT)到达 / 某个文件描述符上有事件(比如读事件写事件)到达 / 超时 这三种情况发生时,执行回调函数。它支持我们在网络编程中学习的 epoll poll select 。相当于做了一个封装使得我们更好使用它们。我们仅需熟悉它的几个常用的API就可以在屏蔽底层细节的情况下实现功能。

        头文件是#include<event2/event.h>或者#include<event.h>

        编译命令g++ 你的文件名 -o 可执行文件名 -levent

我们将会用到的接口:

event_init(void);
event_dispatch(void);
evsignal_new();//底层是 event_new();
evtimer_new();//底层是 event_new();
event_add();
event_free();
event_base_free();

下面我们使用示例代码详细解释它们的功能。 

2.示例代码:

我们先使用evsignal_new再使用event_new。他俩的区别我写在了注释中。

#include<stdio.h>//printf
#include<event.h>
#include<stdlib.h>//exit
#include<signal.h>//SIGINT
void fun1(int fd,short ev,void* arg){
  if(ev==EV_SIGNAL){
    printf("sig==%d\n", fd);
  }
}
void fun2(int fd,short ev,void* arg){
  if(ev&EV_TIMEOUT){
    printf("timeout\n");
  }
}
int main(){
  struct event_base *base = event_init();//初始化事件基础结构
  if(base==NULL)exit(1);
  struct event *sig_ev = evsignal_new(base, SIGINT, fun1, NULL);//SIGINT信号接受会调用fun1,而不是终止程序
  // 这其实是一个宏 #define evsignal_new(b, x, cb, arg) event_new((b), (x), EV_SIGNAL | EV_PERSIST, (cb), (arg))
  //宏替换后,EV_PERSIST被添加,也就是说SIGINT信号触发后,自动添加,这样就可以连续触发。这与evtimer_new不一样,它虽然也是宏替换但是没有EV_PERSIST标识

  if(sig_ev==NULL)exit(1);
  event_add(sig_ev, NULL);//创建好sig_ev事件之后,将它添加到base中
  struct event *time_ev = evtimer_new(base, fun2, NULL);//创建定时器事件,超时调用fun2
  if(time_ev==NULL)exit(1);
  struct timeval tv{3,0};
  event_add(time_ev, &tv);//tv中的时间到期之后调用time_ev指向的fun2函数

  event_base_dispatch(base);//启动事件循环,开始处理事件

  //清理两个事件和事件基础结构base
  event_free(time_ev);
  event_free(sig_ev);
  event_base_free(base);
  return 0;
}

编译:

g++ 你的文件名 -o 可执行文件名-levent

运行起来后:
你键入Ctrl+c,打印sig=2,因为底层有EV_PERSIST,所以SIGINT触发后,还会继续添加。

到达5秒后,将打印time out,但是超时事件不再被触发。


使用event_new:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <event.h>
#include <signal.h>
void sig_cb(int fd, short ev, void* arg)
{
    if ( ev & EV_SIGNAL )
    {
        printf("sig=%d\n",fd);
    }
}
void time_cb(int fd, short ev, void* arg)
{
    if ( ev & EV_TIMEOUT )
    {
        printf("time out\n");
    }
}
int main()
{
    struct event_base * base = event_init();
    if ( base == NULL )
    {
        exit(1);
    }

    struct event *sig_ev = event_new(base, SIGINT, EV_SIGNAL, sig_cb, NULL); // 只触发一次,必须通过event_add()重新添加才能重新触发
    // struct event *sig_ev = event_new(base, SIGINT, EV_SIGNAL | EV_PERSIST, sig_cb, NULL); // 设置了 EV_PERSIST 标志,事件触发后自动重新添加
    if ( sig_ev == NULL )
    {
        exit(1);
    }
    event_add(sig_ev,NULL);
  

    struct event *time_ev = event_new(base, -1, EV_TIMEOUT, time_cb, NULL);//只触发一次,必须通过event_add()重新添加才能重新触发
    // struct event *time_ev = event_new(base, -1, EV_TIMEOUT | EV_PERSIST, time_cb, NULL); // 设置了 EV_PERSIST 标志,事件触发后自动重新添加
    if ( time_ev == NULL )
    {
        exit(1);
    }
    struct timeval tv = {2,0};
    event_add(time_ev,&tv);

    event_base_dispatch(base);

    event_free(time_ev);
    event_free(sig_ev);
    event_base_free(base);
}

两个事件都是一次触发。不再添加。

当我们放开注释的两行后,两个事件都会被触发多次。

我个人认为,event_new更易用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值