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.
Libevent用例解读
最新推荐文章于 2025-04-01 14:59:05 发布
