Libevent簡介
The libevent API provides a mechanism to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached. Furthermore, libevent also support callbacks due to signals or regular timeouts.
Libevent的API提供了這樣的一套機制:2.庫的使用
當指定文件描述符中一個特定的事件發生,或者超時時間到達后執行指定的回調函數。
此外,libevent回調功能也支持由信號或者常規的超時觸發。
注意其許可協議為BSD-style的協議,可以在商業級產品中采用而不必開源。
1.編譯安裝
ubuntu下可以使用apt的方法直接安裝:
~$ sudo apt-get install libevent
或者使用
~$ wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz
~$ tar –xzvf libevent-1.4.13-stable.tar.gz
~$ cd libevent-1.4.13-stable
~$ ./configure
~$ make
~$ sudo make install
可以從這幾個簡單的例子中了解到libevent的基本使用方法。編譯時需加上 "-levent"參數。
2.1.I/O事件(對應EV_READ、EV_WRITE)
下面提供了一個有所省略簡單使用libevent返回系統時間的服務端程序片段。
1
void get_time(int fd,short event,struct event *arg) /**//*獲取系統時間并將其往回write*/
2

{
3
……
4
localtime_r(&now,&t);
5
asctime_r(&t,buf);
6
write( fd,buf,strlen(buf) );
7
……
8
}
9
void con_accept(int fd,short event,void *arg) /**//*提供給事件的回調函數,接收一個連接*/
10

{
11
struct sockaddr_in s_in;
12
socklen_t len = sizeof(s_in);
13
int ns = accept(fd,(struct sockaddr *) &s_in,&len);
14
struct event *ev = malloc(sizeof(struct event));
15
event_set(ev,ns,EV_WRITE,(void *)get_time,ev);
16
event_add(ev,NULL);
17
}
18
19
int main()
20

{
21
int sockfd = socket(PF_INET,SOCK_STREAM,0);
22
struct sockaddr_in s_in;
23
……
24
bind(sockfd,(struct sockaddr*) &s_in,sizeof(s_in));
25
listen(sockfd,5);
26
event_init(); //libevent初始化
27
28
struct event ev;
29
event_set(&ev,sockfd,EV_READ|EV_PERSIST,con_accept,&ev);
30
//設置事件屬性為可讀、持續,回調函數為con_accept()
31
event_add(&ev,NULL);//添加事件,未設置超時時間
32
event_dispatch();//進入libevent主循環
33
return 0;
34
}
35

void get_time(int fd,short event,struct event *arg) /**//*獲取系統時間并將其往回write*/2


{3
……4
localtime_r(&now,&t);5
asctime_r(&t,buf);6
write( fd,buf,strlen(buf) );7
……8
}9

void con_accept(int fd,short event,void *arg) /**//*提供給事件的回調函數,接收一個連接*/10


{11
struct sockaddr_in s_in;12
socklen_t len = sizeof(s_in);13
int ns = accept(fd,(struct sockaddr *) &s_in,&len);14
struct event *ev = malloc(sizeof(struct event));15
event_set(ev,ns,EV_WRITE,(void *)get_time,ev);16
event_add(ev,NULL);17
}18
19
int main()20


{21
int sockfd = socket(PF_INET,SOCK_STREAM,0);22
struct sockaddr_in s_in;23
……24
bind(sockfd,(struct sockaddr*) &s_in,sizeof(s_in));25
listen(sockfd,5);26
event_init(); //libevent初始化27

28
struct event ev;29
event_set(&ev,sockfd,EV_READ|EV_PERSIST,con_accept,&ev);30
//設置事件屬性為可讀、持續,回調函數為con_accept()31
event_add(&ev,NULL);//添加事件,未設置超時時間32
event_dispatch();//進入libevent主循環33
return 0;34
}35

2.2. 信號處理事件(對應EV_SIGNAL)
1
static void signal_cb(int fd, short event, void *arg)
2

{
3
struct event *signal = arg;
4
printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal));
5
if (called >= 2)
6
event_del(signal); //如果調用了兩次以上,就刪除這個信號
7
called++;
8
}
9
10
int main (int argc, char **argv)
11

{
12
struct event signal_int;
13
event_init();//libevent初始化
14
event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, &signal_int);
15
//設置事件屬性為信號觸發、持續,回調函數為con_accept()
16
event_add(&signal_int, NULL); //添加事件
17
event_dispatch();//進入libevent主循環
18
return 0;
19
}
20
static void signal_cb(int fd, short event, void *arg)2


{3
struct event *signal = arg;4
printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal));5
if (called >= 2)6
event_del(signal); //如果調用了兩次以上,就刪除這個信號7
called++;8
}9

10
int main (int argc, char **argv)11


{12
struct event signal_int;13
event_init();//libevent初始化14
event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, &signal_int); 15
//設置事件屬性為信號觸發、持續,回調函數為con_accept()16
event_add(&signal_int, NULL); //添加事件17
event_dispatch();//進入libevent主循環18
return 0;19
}20

2.3.常規超時處理(對應EV_TIMEOUT)
1
static void timeout_cb(int fd, short event, void *arg)
2

{
3
struct timeval tv;
4
struct event *timeout = arg;
5
int newtime = time(NULL);
6
printf("%s: called at %d: %d\n", __func__, newtime,
7
newtime - lasttime);
8
lasttime = newtime;
9
evutil_timerclear(&tv);
10
tv.tv_sec = 2;
11
event_add(timeout, &tv);
12
}
13
14
int main (int argc, char **argv)
15

{
16
struct event timeout;
17
struct timeval tv;
18
event_init();//libevent初始化
19
evtimer_set(&timeout, timeout_cb, &timeout);
20
//實際上該函數對應的是event_set(timeout, -1, 0, timeout_cb,&timeout)
21
evutil_timerclear(&tv); //如果有時間清理函數則直接對應timerclear(),如果沒有則將tv_sec和tv_usec設置為0
22
23
tv.tv_sec = 2;
24
event_add(&timeout, &tv);
25
lasttime = time(NULL);
26
event_dispatch();
27
return 0;
28
}
29
static void timeout_cb(int fd, short event, void *arg)2


{3
struct timeval tv;4
struct event *timeout = arg;5
int newtime = time(NULL);6
printf("%s: called at %d: %d\n", __func__, newtime,7
newtime - lasttime);8
lasttime = newtime;9
evutil_timerclear(&tv);10
tv.tv_sec = 2;11
event_add(timeout, &tv);12
}13

14
int main (int argc, char **argv)15


{16
struct event timeout;17
struct timeval tv;18
event_init();//libevent初始化19
evtimer_set(&timeout, timeout_cb, &timeout);20
//實際上該函數對應的是event_set(timeout, -1, 0, timeout_cb,&timeout)21
evutil_timerclear(&tv); //如果有時間清理函數則直接對應timerclear(),如果沒有則將tv_sec和tv_usec設置為022

23
tv.tv_sec = 2;24
event_add(&timeout, &tv);25
lasttime = time(NULL);26
event_dispatch();27
return 0;28
}29



