libevent API 介绍

基本应用场景也是使用 libevnet 的基本流程,下面来考虑一个最简单的场景,使用
livevent 设置定时器,应用程序只需要执行下面几个简单的步骤即可。

1)首先初始化 libevent 库,并保存返回的指针
struct event_base * base = event_init();
实际上这一步相当于初始化一个 Reactor 实例;在初始化 libevent 后,就可以注册事件了。

2)初始化事件 event,设置回调函数和关注的事件
evtimer_set(&ev, timer_cb, NULL);
事实上这等价于调用 event_set(&ev, -1, 0, timer_cb, NULL);
event_set 的函数原型是:
void event_set(struct event *ev, int fd, short event, void (*cb)(int,
short, void *), void *arg)
ev:执行要初始化的 event 对象;
fd:该 event 绑定的“句柄”,对于信号事件,它就是关注的信号;
event:在该 fd 上关注的事件类型,它可以是 EV_READ, EV_WRITE, EV_SIGNAL;
cb:这是一个函数指针,当 fd 上的事件 event 发生时,调用该函数执行处理,它有三个参数,
调用时由 event_base 负责传入,按顺序,实际上就是 event_set 时的 fd, event 和 arg;
arg:传递给 cb 函数指针的参数;
由于定时事件不需要 fd,并且定时事件是根据添加时(event_add)的超时值设定的,因此
这里 event 也不需要设置。
这一步相当于初始化一个 event handler,在 libevent 中事件类型保存在 event 结构体中。
注意:libevent 并不会管理 event 事件集合,这需要应用程序自行管理;

3)设置 event 从属的 event_base
event_base_set(base, &ev);
这一步相当于指明 event 要注册到哪个 event_base 实例上;

4)是正式的添加事件的时候了
event_add(&ev, timeout);
基本信息都已设置完成,只要简单的调用 event_add()函数即可完成,其中 timeout 是定时值;

这一步相当于调用 Reactor::register_handler()函数注册事件。

5)程序进入无限循环,等待就绪事件并执行事件处理
event_base_dispatch(base);

NOTE:在你使用任何有意思的Libevent函数之前,你需要分配一个或多个event_base结构.每一个event_base结构含有一组events,并且可以告知你哪一些events是就绪的.

就是一个event_base可以有一个或一组event

下面的例子中 base就有多个event

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>

#include <event.h>

#define PORT        25341
#define BACKLOG     5
#define MEM_SIZE    1024

struct event_base* base;
struct sock_ev {
    struct event* read_ev;
    struct event* write_ev;
    char* buffer;
};

void release_sock_event(struct sock_ev* ev)
{
    event_del(ev->read_ev);
    free(ev->read_ev);
    free(ev->write_ev);
    free(ev->buffer);
    free(ev);
}

void on_write(int sock, short event, void* arg)
{
    char* buffer = (char*)arg;
    send(sock, buffer, strlen(buffer), 0);

    free(buffer);
}

void on_read(int sock, short event, void* arg)
{
    struct event* write_ev;
    int size;
    struct sock_ev* ev = (struct sock_ev*)arg;
    ev->buffer = (char*)malloc(MEM_SIZE);
    bzero(ev->buffer, MEM_SIZE);
    size = recv(sock, ev->buffer, MEM_SIZE, 0);
    printf("receive data:%s, size:%d\n", ev->buffer, size);
    if (size == 0) {
        release_sock_event(ev);
        close(sock);
        return;
    }
    event_set(ev->write_ev, sock, EV_WRITE, on_write, ev->buffer);
    event_base_set(base, ev->write_ev);
    event_add(ev->write_ev, NULL);
}

void on_accept(int sock, short event, void* arg)
{
    struct sockaddr_in cli_addr;
    int newfd, sin_size;
    struct sock_ev* ev = (struct sock_ev*)malloc(sizeof(struct sock_ev));
    ev->read_ev = (struct event*)malloc(sizeof(struct event));
    ev->write_ev = (struct event*)malloc(sizeof(struct event));
    sin_size = sizeof(struct sockaddr_in);
    newfd = accept(sock, (struct sockaddr*)&cli_addr, &sin_size);
    event_set(ev->read_ev, newfd, EV_READ|EV_PERSIST, on_read, ev);
    event_base_set(base, ev->read_ev);
    event_add(ev->read_ev, NULL);
}

int main(int argc, char* argv[])
{
    struct sockaddr_in my_addr;
    int sock;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    int yes = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(PORT);
    my_addr.sin_addr.s_addr = INADDR_ANY;
    bind(sock, (struct sockaddr*)&my_addr, sizeof(struct sockaddr));
    listen(sock, BACKLOG);

    struct event listen_ev;
    base = event_base_new();
    event_set(&listen_ev, sock, EV_READ|EV_PERSIST, on_accept, NULL);
    event_base_set(base, &listen_ev);
    event_add(&listen_ev, NULL);
    event_base_dispatch(base);

    return 0;
时间: 2024-10-13 19:43:22

libevent API 介绍的相关文章

Linux平台上SQLite数据库教程(二)——C语言API介绍

Linux平台上SQLite数据库教程(二)--C语言API介绍 前言:本文将介绍几个基本的SQLite3数据库的C语言API接口,主要用到两个文件:sqlite3.c.sqlite3.h.源码地址:https://github.com/AnSwErYWJ/SQLite. 打开数据库 1.原型: int sqlite3_open( const char* filename, /* 数据库文件名, 必须为 UTF-8 格式 */ sqlite3** ppDB /* 输出: SQLite 数据库句柄

CasperJS API介绍

一.使用标准JavaScript对象作为可选参数构造CasperJS实例 1 直接在create()函数里面使用 var casper = require('casper').create({ clientScripts: [ 'includes/jquery.js', // These two scripts will be injected in remote 'includes/underscore.js' // DOM on every request ], pageSettings:

WKWebView与JS交互实战技巧之API介绍

前言 前一章我给大家介绍了iOS与HTML5的交互,用的是UIWebView,今天给大家介绍另外一种基于 iOS 8 新推出的 WKWebView 组件,构建出自己的混合开发框架. WKWebView 简介 WKWebView 是苹果在 iOS 8 中引入的新组件,目的是给出一个新的高性能的 Web View 解决方案,摆脱过去 UIWebView 的老旧笨重特别是内存占用量巨大的问题. 苹果将 UIWebViewDelegate 与 UIWebView 重构成了 14 个类和 3 个协议,引入

CEPH OBJECTSTORE API介绍

Thomas是本人在Ceph中国社区翻译小组所用的笔名,该文首次发布在Ceph中国社区,现转载到本人博客,以供大家传阅 CEPH OBJECTSTORE API介绍 本文由 Ceph中国社区-Thomas翻译,陈晓熹校稿 . 英文出处:THE CEPH OBJECTSTORE API 欢迎加入 翻译小组 简介 object store是Ceph OSD的一部分,它完成实际的数据存储.当前有三种不同的object store可用: FileStore: 文件系统+日志后备的存储 KeyValueS

SharePoint 2013 Excel Services REST API介绍

原文:SharePoint 2013 Excel Services REST API介绍 前言:Excel Services 中的 REST API 是 Microsoft SharePoint Server 2010 的新增项.利用 REST API,可通过 URL 直接访问工作簿部件或元素. 一.REST 服务基于两个要求: 用于定位网络资源的寻址方案 用于返回这些资源的表示形式的方法 二.REST URL基本URI的三个组成部分是: REST aspx 页 URI:http://<Serv

libevent简单介绍和使用

<pre class="html" name="code">libevent接口的使用是简单easy的.关键还是一些其他技术须要深入了解.如epoll! 以下文章来自open经验库: libevent是一个基于事件触发的网络库,memcached底层也是使用libevent库. 整体来说,libevent有以下一些特点和优势: * 事件驱动,高性能: * 轻量级,专注于网络: * 跨平台,支持 Windows.Linux.Mac Os等: * 支持多种

Android无线测试之—UiAutomator UiScrollable API介绍三

获取列表子元素 一.相关API介绍 返回值 API 描述 UiObject getChildByDescription(UiSelector childPattern, String text, boolean allowScrollSearch) 是否允许滚动查看获取具备UiSelector条件元素集合后再以文本描述条件查找对象 UiObject getChildByDescription(UiSelector childPattern, String text) 默认滚动获取具备UiSele

Commons-lang API介绍

4.1 Commons-lang API介绍 4.1.1 StringUtils 4.1.2 StringEscapeUtils 4.1.3 ArrayUtils 4.1.4 DateUtils 4.1.5 DateFormatUtils 4.1.6 RandomUtils 4.1.7 NumberUtils 4.1.8 FieldUtils 4.1.9 CharUtils 4.1.10 BooleanUtils   4.1.11 ExceptionUtils 1    StringUtils方

UNIX网络编程-基本API介绍(一)

1.基本结构 大多数套接口函数都需要一个指向套接口地址结构的指针作为参数.每个协议族都定义它自己的套接口地址结构.这些结构的名字均以“sockaddr_”开头,并以对应每个协议族的唯一后缀结束. 1.1 IPv4套接口地址结构 也称为“网际套接口地址结构”,以“sockaddr_in”命名,在头文件<netinet/in.h>中. struct in_addr { in_addr_t s_addr; //32为IP地址 }; struct sockaddr_in { uint8 sin_len