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. SSH KEY 批量分发

    代码 #!/bin/sh . /etc/init.d/functions ];then echo "sh $0 arg0" exit fi for ip in 172.23.216 ...

  2. Git详解之五:分布式Git

    为了便于项目中的所有开发者分享代码,我们准备好了一台服务器存放远程 Git 仓库.经过前面几章的学习,我们已经学会了一些基本的本地工作流程中所需用到的命令.接下来,我们要学习下如何利用 Git 来组织 ...

  3. C#学习之设计模式:工厂模式

    最近研究一下设计模式中工厂模式的应用,在此记录如下: 什么是工厂模式? 工厂模式属于设计模式中的创造型设计模式的一种.它的主要作用是协助我们创建对象,为创建对象提供最佳的方式.减少代码中的耦合程度,方 ...

  4. mysql 错误信息

    1 连接MySQL错误:Can't connect to MySQL server (10060) link:>>>  http://blog.csdn.net/testcs_dn/ ...

  5. Java源码解读(一)——HashMap

    HashMap作为常用的一种数据结构,阅读源码去了解其底层的实现是十分有必要的.在这里也分享自己阅读源码遇到的困难以及自己的思考. HashMap的源码介绍已经有许许多多的博客,这里只记录了一些我看源 ...

  6. 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数

    问题描述: 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数. 算法一: 对数组a[n]进行冒泡排序,如果冒泡所得的最值和前一个最值相等,则该最值为重复的数. 分析: 该算法时间复杂 ...

  7. volatile关键字的特性总结

    当一个变量定义为volatile后,它将具备两个特性: 1.保证此变量对所有线程的可见性,所谓"可见性",,是指当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的. ...

  8. 理解css伪类和伪元素

    伪类就是可以通过直接添加一个类样式达到同等效果,而伪元素,则需要先添加一个元素,然后在元素上添加样式才能达到同等效果 伪类 :active 向被激活的元素添加样式. :focus 向拥有键盘输入焦点的 ...

  9. Koa2和相关资料

    koa2是什么我就不介绍,这里只是收集一些有用的资料,koa这里默认就指koa2了额. koa介绍 koa(GitHub) koa(npm) 文档 Usage Guide Error Handling ...

  10. TensorBoard的使用(结合线性模型)

    TensorBoard是TensorFlow 的可视化工具.主要为了更方便用户理解 TensorFlow 程序.调试与优化,用户可以用 TensorBoard 来展现 TensorFlow 图像,绘制 ...