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. css挖坑爬坑之div高宽相等

    目标效果 对于这么一个头像,外面是一个圆角的div里面是一个img,对于外面的div我要使他高度等于宽度. 发现问题 开始的时候设置宽度为100%然后高度为100%,这样子对于宽度来说的话可以撑满页面 ...

  2. js介绍

    ---恢复内容开始--- js介绍 最近学习了js,那么我今天给大家介绍下js.希望对初学者有些帮助. js就是常说的JavaScript.JavaScript是目前世界上最流行的编程语言之一.这门语 ...

  3. jquery.cookie的path坑

    在使用jquery.cookie设置cookie的时候,通常都是直接设置,没有针对path,domain和expires等进行具体的设置,这会导致,同一个cookie的key对应多个value. 1. ...

  4. 一图看懂java内存模型

    熟话说一张好图胜过千言万语,在此便将java内存模型重新整理了一次,将细节标注到图中献给需要的同学:

  5. Python的类与类型

    1.经典类与新式类 在了解Python的类与类型前,需要对Python的经典类(classic classes)与新式类(new-style classes)有个简单的概念. 在Python 2.x及 ...

  6. 解决myeclipse部署按钮不能点

    找到MyEclipse的工作路径(一般点开myeclipse是会显示),然后到这个目录中去“\.metadata\.plugins\org.eclipse.core.runtime\.settings ...

  7. vue2.0 关于Vue实例的生命周期

    什么是生命周期 Vue实例有一个完整的生命周期,也就是从开始创建.初始化数据.编译模板.挂载Dom.渲染→更新→渲染.卸载等一系列过程,我们称这是Vue的生命周期.通俗说就是Vue实例从创建到销毁的过 ...

  8. Appium 命令行模式下遇到的问题总结及解决方案 npm ERR! tar.unpack unzip(或者untar) error

    安装了GUI Appium后,卸载删除问题后,使用命令行模式安装. 一. 遇到问题: nalideMacBook-Pro:~ nali$ npm install -g appium npm ERR! ...

  9. easyHOOK socket send recv

    代码比较简单,就不做注释了.  包含一个sockethookinject.DLL 和sockethook.exe 有一点不清楚, SetExclusiveACL可以添加当前线程的hook, 但是eas ...

  10. windows 下进程池的操作

    在Windows上创建进程是一件很容易的事,但是在管理上就不那么方便了,主要体现在下面几个方面: 1. 各个进程的地址空间是独立的,想要在进程间共享资源比较麻烦 2. 进程间可能相互依赖,在进程间需要 ...