赞
踩
Libevent是一个I/O框架库,具有如下特点:
①跨平台支持。
②统一事件源。Libevent对I/O事件,信号和定时事件提供统一的处理
③线程安全。Libevent使用libevent_pthreads库来提供线程安全支持
④基于Reactor模式实现(即主线程负责事件的产生,其余线程负责对事件的处理)
首先注册事件,需要有描述符fd,事件以及回调函数fun。然后交给libevent,libevent通过底层封装的I/O复用方法来进行事件循环的检测,最后调用回调函数进行处理
所以对于用户只需要进行:
①调用libevent实例
②注册事件
③启动事件循环
对于调用回调函数,这个由与用户之前在注册事件的时候已经写好了回调函数,所以最后通过libevent进行处理
#define EV_TIMEOUT //定时事件
#define EV_READ //可读事件
#define EV_WRITE //可写事件
#define EV_SIGNAL //信号事件
#define EV_PERSIST //永久事件
/*边沿触发事件,需要I/O复用系统调用支持,比如epoll*/
#define EV_ET
#include <stdio.h> #include <unistd.h> #include <assert.h> #include <unistd.h> #include <event.h> #include <signal.h> void signal_cb(int fd,short event,void* arg) { if(event&EV_SIGNAL) { printf("sig=%d\n",fd); } } void timeout_cb(int fd,short event,void* arg) { if(event&EV_TIMEOUT) { printf("time out\n"); } } int main() { //调用libevent示例 struct event_base* base=event_init(); //注册信号事件 struct event* signal_event=evsignal_new(base,SIGINT,signal_cb,NULL); event_add(signal_event,NULL); //注册超时事件 struct timeval tv = {2,0}; struct event* timeout_event=evtimer_new(base,timeout_cb,NULL); event_add(timeout_event,&tv); //启动事件循环 event_base_dispatch(base); //free event_free(signal_event); event_free(timeout_event); event_base_free(base); }
由于上述代码中并没有将注册的事件变为永久事件,因此一次之后就结束了
所以程序运行结果如下:
服务器端:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <event.h> //创建监听套接字 int socket_init() { int sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1) { return -1; } struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family=AF_INET; saddr.sin_port=htons(6000); saddr.sin_addr.s_addr=inet_addr("127.0.0.1"); int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr)); if(res==-1) { return -1; } res=listen(sockfd,5); if(res==-1) { return -1; } return sockfd; } void recv_cb(int fd,short event,void* arg) { if(event&EV_READ) { char buff[1024]={0}; int n=recv(fd,buff,1024,0); if(n<=0) { struct event** p_cev=(struct event**)arg; event_free(*p_cev); free(p_cev); close(fd); printf("client close\n"); return ; } printf("recv:%s\n",buff); send(fd,"ok",2,0); } } void accept_cb(int fd,short event,void* arg) { struct event_base* base=(struct event_base*)arg; if(event&EV_READ) { struct sockaddr_in caddr; int len=sizeof(caddr); int c=accept(fd,(struct sockaddr*)&caddr,&len); if(c<0) { return ; } printf("accept c=%d\n",c); struct event** p_cev=(struct event**)malloc(sizeof(struct event*)); if(p_cev==NULL) { return ; } *p_cev=event_new(base,c,EV_READ|EV_PERSIST,recv_cb,p_cev); if(*p_cev==NULL) { close(c); return ; } event_add(*p_cev,NULL); } } int main() { struct event_base* base=event_init(); int sockfd=socket_init(); assert(sockfd!=-1); struct event* sock_ev=event_new(base,sockfd,EV_READ|EV_PERSIST,accept_cb,base); event_add(sock_ev,NULL); event_base_dispatch(base); event_free(sock_ev); event_base_free(base); return 0; }
客户端:
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <assert.h> int main() { int sockfd=socket(AF_INET,SOCK_STREAM,0); assert(sockfd!=-1); struct sockaddr_in saddr; memset(&saddr,0,sizeof(saddr)); saddr.sin_family=AF_INET; saddr.sin_port=htons(6000); saddr.sin_addr.s_addr=inet_addr("127.0.0.1"); int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr)); assert(res!=-1); while(1) { printf("please input:\n"); char buff[1024]={0}; fgets(buff,1024,stdin); if(strncmp(buff,"end",3)==0) { break; } int n=send(sockfd,buff,strlen(buff),0); if(n<=0) { printf("send error\n"); break; } memset(buff,0,1024); n=recv(sockfd,buff,1024,0); if(n<=0) { printf("recv error\n"); } printf("buff=%s\n",buff); } close(sockfd); exit(0); }
程序运行结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。