Libevent用例解读

Libevent是一个跨平台的事件驱动库,适用于多种操作系统平台。该库可根据编译/运行环境自动切换底层事件驱动机制,有效提升系统性能并增强软件的可移植性。本文通过一个简单示例介绍了libevent的基本使用方法。

 libevent是一个跨平台的事件驱动库。如果你将要开发的应用程序需要支持以上所列出的平台中的两个以上,那么强烈建议你采用这个库,即使你的应用程序只需要支持一个平台,选择 libevent也是有好处的,因为它可以根据编译/运行环境切换底层的事件驱动机制,这既能充分发挥系统的性能,又增加了软件的可移植性。它封装并且隔离了事件驱动的底层机制,除了一般的文件描述符读写操作外,它还提供有读写超时、定时器和信号回调,另外,它还允许为事件设定不同的优先级,libevent 1.40还提供dns和http协议的异步封装,这一切都让这个库尤其适合于事件驱动应用程序的开发。

对libevent的理解最好就是阅读其代码,可以在(www.monkey.org/~provos/libevent/)下载。下面我们通过它提供的一个简单用例,进行一定的解读,对其有个大概的了解。
调用API接口如下:
/*功能:设置事件信息
参数解析:
ev结构信息,返回信息
events要进行触发的事件 EV_TIMEOUT、EV_READ 、EV_WRITE 、EV_SIGNAL、 EV_PERSIST
void (*callback)(int, short, void *)为回调函数
void *arg为自设置值,回调用时返回
*/
event_set(struct event *ev, int fd, short events, void (*callback)(int, short, void *), void *arg)

/*功能: 回调函数
参数解析:
int fd是在event_set的int fd
short event是在event_set的events
void* arg是在event_set的void *arg
*/
void (*callback)(int, short, void *)

/*功能: 增加事件
参数解析:
struct event *ev为event_set时的ev
struct timeval *tv为超时时间
return:-1失败,其它成功
*/
int event_add(struct event *ev, struct timeval *tv)


/*功能: 删除事件
return:-1失败,其它成功
*/
int event_del(struct event *ev)

/*功能: 循环处理事件
return:-1失败,0为正常,1为没有注册事件
*/
int event_dispatch(void)


/*
* Compile with:
* cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
*/

#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
#else
#include <windows.h>
#endif
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <event.h>

void fifo_read(int fd, short event, void *arg)
{
    char buf[255];
    int len;
    struct event *ev = arg;
#ifdef WIN32
    DWORD dwBytesRead;
#endif

    /* Reschedule this event */
    event_add(ev, NULL);/*重新添加事件,事件触发一次后删除(内部实现机制不同而不同,但是再次添加会将原来的删除再次添加,如此写比较通用)*/

    fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p/n",
        fd, event, arg);
#ifdef WIN32
    len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL);

    // Check for end of file.
    if(len && dwBytesRead == 0) {
        fprintf(stderr, "End Of File");
        event_del(ev);/*删除事件*/
        return;
    }

    buf[dwBytesRead + 1] = '/0';
#else
    len = read(fd, buf, sizeof(buf) - 1);

    if (len == -1) {
        perror("read");
        return;
    } else if (len == 0) {
        fprintf(stderr, "Connection closed/n");
        return;
    }

    buf[len] = '/0';
#endif
    fprintf(stdout, "Read: %s/n", buf);
}

int
main (int argc, char **argv)
{
    struct event evfifo;
#ifdef WIN32
    HANDLE socket;
    // Open a file.
    socket = CreateFile("test.txt",     // open File
            GENERIC_READ,                 // open for reading
            0,                            // do not share
            NULL,                         // no security
            OPEN_EXISTING,                // existing file only
            FILE_ATTRIBUTE_NORMAL,        // normal file
            NULL);                        // no attr. template

    if(socket == INVALID_HANDLE_VALUE)
        return 1;

#else
    struct stat st;
    char *fifo = "event.fifo";
    int socket;

    if (lstat (fifo, &st) == 0) {
        if ((st.st_mode & S_IFMT) == S_IFREG) {
            errno = EEXIST;
            perror("lstat");
            exit (1);
        }
    }

    unlink (fifo);
    if (mkfifo (fifo, 0600) == -1) {
        perror("mkfifo");
        exit (1);
    }

    /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
#ifdef __linux
    socket = open (fifo, O_RDWR | O_NONBLOCK, 0);
#else
    socket = open (fifo, O_RDONLY | O_NONBLOCK, 0);
#endif

    if (socket == -1) {
        perror("open");
        exit (1);
    }

    fprintf(stderr, "Write data to %s/n", fifo);
#endif
    /* 初始事件库 */
    event_init();

    /* 生成一个事件信息 */
#ifdef WIN32
    event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo);
#else
    event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);
#endif

    /*添加事件*/
    event_add(&evfifo, NULL);
   
    event_dispatch();
#ifdef WIN32
    CloseHandle(socket);
#endif
    return (0);
}

在(unx.ca/log/tag/libevent/)中有些简单的使用事例,如http server、 Non-blocking DNS.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值