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提供了这样的一套机制: 当指定文件描述符中一个特定的事件发生,或者超时时间到达后执行指定的回调函数。 此外,libevent回调功能也支持由信号或者常规的超时触发。 注意其许可协议为BSD-style的协议,可以在商业级产品中采用而不必开源。
1.编译安装
ubuntu下可以使用apt的方法直接安装:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ sudo apt-get install libevent
或者使用
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz ![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ tar –xzvf libevent-1.4.13-stable.tar.gz ![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ cd libevent-1.4.13-stable ![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ ./configure ![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ make ![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) ~$ sudo make install ![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
2.库的使用
可以从这几个简单的例子中了解到libevent的基本使用方法。编译时需加上 "-levent"参数。
2.1.I/O事件(对应EV_READ、EV_WRITE)
下面提供了一个有所省略简单使用libevent返回系统时间的服务端程序片段。
1![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) void get_time(int fd,short event,struct event *arg) /**//*获取系统时间并将其往回write*/ 2![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 3 …… 4 localtime_r(&now,&t); 5 asctime_r(&t,buf); 6 write( fd,buf,strlen(buf) ); 7 …… 8 } 9![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) void con_accept(int fd,short event,void *arg) /**//*提供给事件的回调函数,接收一个连接*/ 10![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 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![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 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![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 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![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
2.2. 信号处理事件(对应EV_SIGNAL)
1 static void signal_cb(int fd, short event, void *arg) 2![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 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![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 10 int main (int argc, char **argv) 11![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 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![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
2.3.常规超时处理(对应EV_TIMEOUT)
1 static void timeout_cb(int fd, short event, void *arg) 2![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 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![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 14 int main (int argc, char **argv) 15![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) ![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif) { 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![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif) 23 tv.tv_sec = 2; 24 event_add(&timeout, &tv); 25 lasttime = time(NULL); 26 event_dispatch(); 27 return 0; 28 } 29![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
|