在libevent中为了监听某种事件的发生,设置事件触发后的回调函数,也就是说对该事件注册到当前的IO模型中。socket
使用`event_new`函数来对事件进行初始化。函数
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);/* 回调函数 */ struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, event_callback_fn cb, void *arg); void event_free(struct event *event);
/* * base:event_base类型,event_base_new的返回值 * fd:监听的fd,listen的fd * what:事件的类型及属性 * cb:绑定的回调函数 * arg:给回调函数的参数 */
其中,事件类型及属性以下:oop
#define EV_TIMEOUT 0x01 /*定时事件*/ #define EV_READ 0x02 /*I/O事件*/ #define EV_WRITE 0x04 /*I/O事件*/ #define EV_SIGNAL 0x08 /*信号*/ #define EV_PERSIST 0x10 /*永久事件 */ #define EV_ET 0x20 /*边沿触发*/
此外,还有一个函数`event_assgin`,它多了一个event参数:spa
int event_assign(struct event *event, struct event_base *base, evutil_socket_t fd, short what, void (*callback)(evutil_socket_t, short, void *), void *arg);
虽然已经初始化了事件,可是该事件并不会被触发,缘由在于咱们并无激活该事件。线程
`event_add`函数提供了激活事件的功能。debug
int event_add(struct event *ev, const struct timeval *tv);
若是是一个(non-pending)未注册`ev`,调用`event_add`函数会注册该事件(变为pending状态)。若是是一个(pending)注册过的`ev`,调用该函数会在tv时间后从新注册该事件。成功返回0,失败返回-1。code
#include <event2/event.h> void cb_func(evutil_socket_t fd, short what, void *arg) { const char *data = arg; printf("Got an event on socket %d:%s%s%s%s [%s]", (int) fd, (what&EV_TIMEOUT) ? " timeout" : "", (what&EV_READ) ? " read" : "", (what&EV_WRITE) ? " write" : "", (what&EV_SIGNAL) ? " signal" : "", data); } void main_loop(evutil_socket_t fd1, evutil_socket_t fd2) { struct event *ev1, *ev2; struct timeval five_seconds = {5,0}; struct event_base *base = event_base_new(); /* The caller has already set up fd1, fd2 somehow, and make them nonblocking. */ /* 初始化事件 */ ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, cb_func,(char*)"Reading event"); ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, cb_func,(char*)"Writing event"); /* 注册事件 */ event_add(ev1, &five_seconds); event_add(ev2, NULL); /* 循环监听 */ event_base_dispatch(base); }
struct event *event_base_get_running_event(struct event_base *base);
int event_base_once(struct event_base *, evutil_socket_t, short,void (*)(evutil_socket_t, short, void *), void *, const struct timeval *);
void event_active(struct event *ev, int what, short ncalls);
/* * 参数ev为要激活的事件 * what能够为EV_READ, EV_WRITE, and EV_TIMEOUT * ncalls为激活次数 */
#define evtimer_new(base, callback, arg) \ event_new((base), -1, 0, (callback), (arg)) #define evtimer_add(ev, tv) \ event_add((ev),(tv)) #define evtimer_del(ev) \ event_del(ev) #define evtimer_pending(ev, tv_out) \ event_pending((ev), EV_TIMEOUT, (tv_out))
//@param: flags //等待IO事件 #define EVLOOP_ONCE 0x01 //非阻塞,直接返回 #define EVLOOP_NONBLOCK 0x02 //其余的线程中添加事件 #define EVLOOP_NO_EXIT_ON_EMPTY 0x04 int event_base_loop(struct event_base *base, int flags);
int event_base_dispatch(struct event_base *base);
//延迟tv时间后,中止event loop int event_base_loopexit(struct event_base *base, const struct timeval *tv); //马上中止,等同于tv = NULL int event_base_loopbreak(struct event_base *base); //获取退出方式 int event_base_got_exit(struct event_base *base); int event_base_got_break(struct event_base *base);
void event_base_dump_events(struct event_base *base, FILE *f);
#include <sys/types.h> #include <event2/event-config.h> #include <sys/stat.h> #ifndef WIN32 #include <sys/queue.h> #include <unistd.h> #endif #include <time.h> #ifdef _EVENT_HAVE_SYS_TIME_H #include <sys/time.h> #endif #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <event2/event.h> #include <event2/event_struct.h> #include <event2/util.h> struct timeval lasttime; int event_is_persistenet; static void timeout_cb(evutil_socket_t fd, short event, void *arg) { struct timeval newtime, difference; struct event *timeout = arg; double elapsed; evutil_gettimeofday(&newtime, NULL); evutil_timersub(&newtime, &lasttime, &difference); elapsed = difference.tv_sec + (difference.tv_usec / 1.0e6); printf("timeout_cb called at %d: %.3f seconds elapsed.\n", (int)newtime.tv_sec, elapsed); lasttime = newtime; if (! event_is_persistent) { struct timeval tv; evutil_timerclear(&tv); tv.tv_sec = 2; event_add(timeout, &tv); } } int main(int argc, char **argv) { struct event timeout; struct timeval tv; struct event_base *base; int flags; if (argc == 2 && !strcmp(argv[1], "-p")) { event_is_persistent = 1; flags = EV_PERSIST; } else { event_is_persistent = 0; flags = 0; } /* Initalize the event library */ base = event_base_new(); /* Initalize one event */ event_assign(&timeout, base, -1, flags, timeout_cb, (void*)&timeout); evutil_timerclear(&tv); tv.tv_sec = 2; event_add(&timeout, &tv); evutil_gettimeofday(&lasttime, NULL); event_base_dispatch(base); return (0); }