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. (转) Linux中profile、bashrc、bash_profile之间的区别和联系

    原文地址:http://blog.csdn.net/chenchong08/article/details/7833242 /etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登 ...

  2. EditTable-V1.0--续集

    上一个功能有点少,这个V1.0版本是最小集合的. ================================= 双击单元格编辑,可以添加,删除单元格.并且保持相邻单元格不同的背景色. 引用了“M ...

  3. 第三章 go语言 程序的流程控制

    程序的流程控制主要包括三种不同的结构,分别是顺序结构.选择结构和循环结构. ² 顺序结构最为简单,程序执行时,按照语句的顺序自上而下依次执行. ² 选择结构是根据条件表达式的结果选择执行某些语句. ² ...

  4. Check whether a remote server port is open on Linux

    链接:https://www.pixelstech.net/article/1514049471-Check-whether-a-remote-server-port-is-open-on-Linux

  5. C# war3 巨魔精灵 minimap

    弃坑LOL后,无聊的时候玩玩 war3的RPG地图,巨魔与精灵.  玩了一段时间精灵....然后玩魔结果总是找不到人.所以就有了这个想法. 代码纯粹靠搬运. 说下原理,网上有份代码,可以查看当前选中目 ...

  6. css 两端对齐的多种实现方式

    http://www.cnblogs.com/PeunZhang/p/3289493.html

  7. C# 生成二维码 QRCoder

    最近项目上有个需求,需要将某个文件的下载地址生成二维码,并展示到网页上. 目前网上生成二维码的方法有好几种,本文将介绍[QRCoder]生成二维码的方式 一.首先通过VS中的[NUGET]下载并引用Q ...

  8. 深入一致性哈希(Consistent Hashing)算法原理,并附100行代码实现

    转自:https://my.oschina.net/yaohonv/blog/1610096 本文为实现分布式任务调度系统中用到的一些关键技术点分享——Consistent Hashing算法原理和J ...

  9. Java与算法之(11) - 合并排序

    天下事,合久必分,分久必合.合并排序的基本思想正是先分再合. 例如对3, 1这个数列排序,首先是分,分为3和1两个数列,然后再合并并排序.合并需要额外的辅助空间,即建立一个两个数列长度之和的空数组用于 ...

  10. Mvc 模板化的Razor引擎委托

    最近在研究NopCommerce,它后台用的富文本编辑器可根据语言库加载不同语言的编辑器,其中用到了模板化Razor引擎委托,参考这儿 废话不多说,直接上代码. public static class ...