在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); }