libevent--快速入门

一.简介

libevent是一个c语言写的事件驱动库,轻量级,专注于网络,跨平台特性好,支持多种 I/O 多路复用.支持I/O,定时器和信号等事件,允许设置注册事件优先级.

二.基本使用场景和事件流程

(1)初始化事件根基(槽)

struct event_base *event_base_new(void);
struct event_base *event_init(void);
  • event_base_new()函数分配并且返回一个新的具有默认设置的event_base.
  • event_init() 会调用event_base_new()创建一个event_base,并以此初始化一个全局的变量current_base .

例:

struct event_base *base = event_init();

(2)初始化事件event,设置回调函数和关注的事件,并关联对应的事件根基(槽)event_base

typedef void (*event_callback_fn)(evutil_socket_t, short, void*);

struct event *event_new(struct event_base *, evutil_socket_t, short,
event_callback_fn, void *); int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *); void event_set(struct event *ev, int fd, short events,
event_callback_fn, void *arg);
void event_base_set(struct event_base *,struct event*);
  • event_assign()的作用就是把给定的event类型对象的每一个成员赋予一个指定的值。

  • event_new()的实现其实是间接的调用的event_assign(),首先调用mm_malloc分配一块内存,然后调用event_assign来给event类型的对象各个成员赋值。

  • event_set() 使用指定的句柄、关注的事件、事件发生时的回调函数、回调函数的额外参数,初始化设置struct event结构对象,绑定到全局current_base,设置此event结构对象的优先级,默认为current_base中总有限级数的一半

  • event_base_set() 将事件绑定到事件根基,即设置event从属的event_base,指明event注册到哪个event_base实例上

    例:

//SIGINT 信号事件初始化
//假定已创建事件根基struct event_base *base 
//方式一:
struct event sigint_ev;
event_assign(&sigint_ev,base,SIGINT, EV_SIGNAL | EV_PERSIST,sigint_cb,NULL);
//方式二:
struct event sigint_ev ;
event_set(&sigint_ev, SIGINT, EV_SIGNAL | EV_PERSIST, sigint_cb, NULL);
event_base_set(base, &sigint_ev);
//方式三:
struct event *sigint_ev;
sigint_ev = event_new(base,SIGINT,EV_SIGNAL | EV_PERSIST, sigint_cb, NULL);
//方式四:
struct event* sigint_ev = (struct event*)malloc(sizeof(struct event));
//sigint_ev检测非空和置零后,用event_assign 或者event_set + event_base_set 初始化事件.

定时器事件:

#define evtimer_set(ev, cb, arg)    event_set(ev, -1, 0, cb, arg)

信号事件:

#define evsignal_new(base,signum,cb,arg) \
event_new(base,signum,EV_SIGNAL|EV_PERSIST,cb,arg)

(3)添加事件,将事件变成未决态,即,将event加入到event_base中,等待监听

void event_add(struct event* ,struct timeval *);

(4)程序进入无限循环,事件根基event_base开始工作,对注册的event进行监听.若注册的事件的对应事件类型触发,或者超时,会自动触发event对应的回调函数执行

void event_base_dispatch(struct event_base *);
void event_base_loop(struct event_base *,int );

三.入门例子:

文件:test.c

编译:

gcc -o test test.c -levent

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <event.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 1024 typedef struct{
struct event *ev;
char *buf;
struct timeval *tv;
}rw_st; void wr_cb(int fd, short event, void *arg);
void rd_cb(int fd, short event, void *arg); struct event_base *base = NULL;
//定时事件
struct timeval tv;
struct event time_ev;
void time_cb(int fd, short event, void *arg)
{
printf("time_cb : 5s timer wakeup\n");
event_add(&time_ev,&tv);
} //标准输入 读事件
//输入一行,把读事件删掉,添加写事件
void rd_cb(int fd,short event, void *arg)
{
if(event & EV_TIMEOUT){
printf("io read time out(2s)!\n");
return ;
}
rw_st* rd_st = (rw_st*)arg;
int len = read(fd, rd_st->buf, BUF_SIZE);
rd_st->buf[len-1] = '\0';
printf("rd_cb (stdin): %s \n",rd_st->buf); event_del(rd_st->ev);
event_set(rd_st->ev, STDOUT_FILENO, EV_WRITE | EV_PERSIST,
wr_cb,(void*)rd_st);
event_add(rd_st->ev,NULL);
} //标准输出 写事件
//输出,把写事件删掉,添加读事件,边写边读
void wr_cb(int fd, short event, void *arg)
{
rw_st *wr_st = (rw_st*)arg;
printf("wr_cb (stdout): %s\n",wr_st->buf);
memset(wr_st->buf,0,BUF_SIZE);
event_del(wr_st->ev);
event_set(wr_st->ev, STDIN_FILENO, EV_READ | EV_PERSIST,
rd_cb, (void*)wr_st);
event_add(wr_st->ev,wr_st->tv);
} //SIGINT 信号事件
void sigint_cb(int fd, short event, void *arg)
{
struct timeval tv_1s = {1,0};
printf("SIGINT : EXIT IN 1s\n");
event_base_loopexit(base,&tv_1s);
} //SIGHUB 信号事件
void sighup_cb(int fd, short event, void *arg)
{
printf("SIGHUP: EXIT AT ONCE\n");
event_base_loopbreak(base);
} int main()
{
printf("pid = %ld\n",getpid());
base = event_init();
//定时器
tv.tv_sec = 5;
tv.tv_usec = 0;
evtimer_set(&time_ev, time_cb, NULL);//一次性,默认全局的current_base
// event_set(&time_ev,-1,0,time_cb,NULL); // event_base_set(base, &time_ev); //可省,在这里current_base等同base
event_add(&time_ev,&tv); //io 读事件 指针 event_new
char buf[1024] = {0};
struct timeval io_tv = {2,0};
rw_st *rd_st = (rw_st*)malloc(sizeof(rw_st));
memset(rd_st,0,sizeof(rw_st)); struct event *io_ev = (struct event*)malloc(sizeof(struct event));
memset(io_ev,0,sizeof(struct event)); rd_st->ev = io_ev;
rd_st->buf = buf;
rd_st->tv = &io_tv;
event_assign(rd_st->ev,base,STDIN_FILENO,
EV_TIMEOUT | EV_READ | EV_PERSIST,rd_cb,(void*)rd_st);
event_add(rd_st->ev,rd_st->tv); //SIGINT 信号事件
struct event sigint_ev; event_assign(&sigint_ev,base,SIGINT, EV_SIGNAL | EV_PERSIST,sigint_cb,NULL);
// event_set(&sigint_ev, SIGINT, EV_SIGNAL | EV_PERSIST,
// sigint_cb, NULL);
//event_base_set(base, &sigint_ev);
event_add(&sigint_ev,NULL); // struct event *sigint_ev = event_new(base,SIGINT,
// EV_SIGNAL | EV_PERSIST, sigint_cb, NULL);
// event_add(sigint_ev,NULL); //SIGHUP 信号事件
//测试: $ kill -SIGHUP pid
struct event *sighup_ev;
sighup_ev = evsignal_new(base, SIGHUP, sighup_cb, NULL);
event_add(sighup_ev,NULL); event_base_dispatch(base);
//event_base_loop(base,0); event_free(sighup_ev);
event_base_free(base);
free(rd_st); printf("EXIT\n");
return 0;
}

###原创所有,转载注明原文出处.若有错误,欢迎指正,共同学习,谢谢!

学习总结:libevent--简单入门的更多相关文章

  1. SpringMVC学习笔记之---简单入门

    SpringMVC简单入门 (一)什么是MVC设计模式 (1)model:模型数据,业务逻辑 (3)view:呈现模型,与用户进行交互 (3)controller:负责接收并处理请求,响应客户端 (二 ...

  2. 【VS开发】【数据库开发】libevent简单入门和介绍

    libevent是一个基于事件触发的网络库,memcached底层也是使用libevent库,今天学习下. 总体来说,libevent有下面一些特点和优势: * 统一数据源, 统一I/O事件,信号和定 ...

  3. 学习MyBatis之简单入门HelloWorld

    转:https://blog.csdn.net/gaomb_1990/article/details/78299784 一.准备 Eclipse:Luna Service Release 1 (4.4 ...

  4. AngularJS学习笔记一:简单入门

    阿里云网站的前端是AngularJS实现的. 先下载AngularJS的开发工具包,我下载的angular-1.4.0. 在合适位置引入js文件: <script src="angul ...

  5. Spring学习之路——简单入门HelloWorld

    Spring简单介绍 Spring是一个提供了解决J2EE问题的一站式框架. Spring的核心是反转控制,通过配置文件完成业务对象之间的依赖注入,他鼓励一个良好的习惯,就是注入对接口编程而不是对类编 ...

  6. libevent的入门学习-库的安装【转】

    转自:https://blog.csdn.net/lookintosky/article/details/61658067 libevent的入门学习-库的安装最近开始接触Linux应用层的东西,发现 ...

  7. Asp.Net MVC学习总结(一)——Asp.Net MVC简单入门

    一.MVC简单入门 1.1.MVC概念 视图(View) 代表用户交互界面,对于Web应用来说,可以概括为HTML界面,但有可能为XHTML.XML和Applet. 模型(Model) 表示用户对其数 ...

  8. MyBatis学习总结(一)简单入门案例

    MyBatis学习总结(一)简单入门案例 主要内容:本文主要通过对数据库中的use表进行增删改查总结mybatis的环境搭建和基本入门使用 一.需要的jar包: 1.核心包 2.依赖包 3.jdbc数 ...

  9. springboot 学习之路 1(简单入门)

    目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...

  10. 『NiFi 学习之路』入门 —— 下载、安装与简单使用

    一.概述 "光说不练假把式." 官网上的介绍多少让人迷迷糊糊的,各种高大上的词语仿佛让 NiFi 离我们越来越远. 实践是最好的老师.那就让我们试用一下 NiFi 吧! 二.安装 ...

随机推荐

  1. Building an MFC project for a non-Unicode character set is deprecated

    1>------ 已启动生成: 项目: TestSdk, 配置: Debug Win32 ------1>C:\Program Files (x86)\MSBuild\Microsoft. ...

  2. js模块化规范

    1. CommonJS 用于服务端模块化编程,比如nodejs就采用此规范: 一个文件就是一个模块,require方法用来加载模块,该方法读取一个文件并执行,最后返回文件内部的module.expor ...

  3. Gradle、Gradle Wrapper与Android Plugin for Gradle

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  4. 每天学一点Docker(3)(制作你的第一个容器)

    今天开始制作第一个容器,其实很简单 首先你要准备这些条件: 1.一个Ubuntu系统 2.这个系统能够联网,最起码ping www.baidu.com是可以的 这些准备条件准备好了,接下来就开始做准备 ...

  5. 关于linux下的date日期,并以日期给文件命名

    在linux的终端中,我们输入date后会有以下显示: 然后博主也扩展了一下date的基础用法: date + "%-": %y 输出年份的后2位:%Y 输出完整年份 %m 输出月 ...

  6. MapReduce工作原理流程简介

    在MapReduce整个过程可以概括为以下过程: 输入 --> map --> shuffle --> reduce -->输出 输入文件会被切分成多个块,每一块都有一个map ...

  7. 【转】Jenkins 安装与配置

    基本配置: 1.Linux安装配置jdk环境 1.1.上传到 Linux 服务器:例如: 上传至: cd /usr/local 1.2.解压: rpm -ivh jdk-8u111-linux-x64 ...

  8. 表迁移工具的选型-复制ibd的方法

    1.1. 场景 有的时候开放人员自己的库需要帮忙导一些数据,但是表的数据量又很大.虽然说使用mysqldump或mysqlpump也可以导.但是这耗时需要比较久. 记得之前建议开放人员可以直接使用na ...

  9. MariaDB扩展特性--虚拟列

    存在于表中的列,它们的值是根据确定的表达式或者是根据表中其他列的值自动计算的. 虚拟列有两种,分别对应了定义虚拟列的修饰关键词: 'VIRTUAL'修饰词含义为该虚拟列的值会在查询的时候计算生成. ' ...

  10. sql servel 报错:将 expression 转换为数据类型 int 时出现算术溢出错误。

    执行sql语句:SELECT   AVG( DATEDIFF(s,s.CreatedDate,s.SendDate)  ) AS submitTime FROM dbo.SmsSend AS s    ...