[原创]Libevent分析笔记(1)-安装与使用
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
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
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)
21evutil_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
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)
21evutil_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