libevent学习
libevent是一个开源的事件控制机制,如果不想陷入多进程或多线程的困扰,那么libevent将是很合适的工具。
libevent提供了很多的API来管理和控制事件,可用于设计读、写、信号、定时等各种类型的事件处理,其使用主要有一下几个步骤:
1、首先需要初始化一个event_base结构体,它是libevent的入口,形如
struct event_base* base=event_init();
在新版本中推荐使用线程安全的 event_base_new()来替换event_init();
初始化后就建立了一个libevent的基本框架,接下来就是向框架里注册事件和相应的事件回调函数了。
2、设置注册事件和回调函数:
设置事件使用API: event_set,原型:
event_set(struct event *ev, int fd, short event, void (*func)(int, short, void *), void *arg);
ev是声明的event结构体名称;
fd是监视事件对应的文件描述符;
short event是指定事件类型,可以是:EV_READ,EV_WRITE或EV_READ|EV_WRITE,通常配合使用EV_PERSIST,使事件在执行后不被删除,直到调用event_del()。
*func(int, short, void *)是编写好的回调函数指针,指明在监听的事件发生时要做的处理,其中void*是有*arg指定的参数,int 和short则对应与 int fd和 short event;
3、添加事件
事件设置之后,调用API:
event_add(struct event* ev,timeout);
ev是之前设置的event结构体指针,timeout是超时设置,没有可填NULL;
至此,对事件的初始化和设置已完成。
4、最后一步是事件的运行
调用: event_base_dispatch(base);
这是一个无线循环,还有很多的API提供各种不同需要,如:
event_base_set(),event_base_dispatch(), event_base_loop(), bufferevent_base_set() 等
简单的例子,libevent配合socket非常方便地完成监听多客户端的连接(部分代码):
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;
}
以上只是简单的使用步骤,后续还有很多其他的API和使用介绍