libevent函数库核心思想
/*** epoll_loop.c ***/ #include<stdio.h> #include<sys/epoll.h> #include<sys/socket.h> #include<arpa/inet.h> #include<fcntl.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<stdlib.h> #include<time.h> #define MAX_EVENTS 2014 #define BUFLEN 4096 #define SERV_PORT 8080 void recvdata(int fd,int events,void *arg); void senddata(int fd,int events,void *arg); struct myevent_s { int fd; int events; void *arg; void (*call_back)(int fd,int events,void *arg); int status; char buf[BUFLEN]; int len; long last_active; }; int g_efd; struct myevent_s g_events[MAX_EVENTS + 1]; void eventset(struct myevent_s *ev,int fd,void (*call_back)(int,int,void*),void *arg) { ev->fd = fd; ev->call_back = call_back; ev->events = 0; ev->arg = arg; ev->status = 0; ev->last_active = time(NULL); return; } void eventadd(int efd,int events,struct myevent_s *ev) { struct epoll_event epv = {0,{0}}; int op; epv.data.ptr = ev; epv.events = ev->events = events; if(ev->status == 1) { op = EPOLL_CTL_MOD; } else { op = EPOLL_CTL_ADD; ev->status = 1; } if(epoll_ctl(efd,op,ev->fd,&epv) < 0) { printf("event add failed [fd=%d],evens[%d]\n",ev->fd,events) ; } else { printf("event add OK[fd=%d],op = %d,evens[%0X]\n",ev->fd,op,events) ; } return; } void eventdel(int efd,struct myevent_s *ev) { struct epoll_event epv = {0,{0}}; if(ev->status != 1) { return; } epv.data.ptr = ev; ev->status = 0; epoll_ctl(efd,EPOLL_CTL_DEL,ev->fd,&epv); return; } void acceptconn(int lfd,int events,void *arg) { struct sockaddr_in cin; socklen_t len = sizeof(cin); int cfd,i; if((cfd = accept(lfd,(struct sockaddr *)&cin,&len)) == -1) { if(errno != EAGAIN && errno != EINTR) { } printf("%s : accept,%s \n",__func__,strerror(errno)); return ; } do { for(i = 0; i < MAX_EVENTS; i++) { if(g_events[i].status == 0) { break; } } if(i == MAX_EVENTS) { printf("%s: max connect limit[%d]\n]",__func__,MAX_EVENTS) ; return; } int flag = 0; if((flag = fcntl(cfd,F_SETFL,O_NONBLOCK)) < 0) { printf("%s : accept,%s \n",__func__,strerror(errno)); break; } eventset(&g_events[i],cfd,recvdata,&g_events[i]); eventadd(g_efd,EPOLLIN,&g_events[i]); }while(0); printf("new connect [%s:%d][time:%ld],pos[%d]\n", inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),g_events[i].last_active,i); return; } void recvdata(int fd,int events,void *arg) { struct myevent_s *ev = (struct myevent_s *)arg; int len; len = recv(fd,ev->buf,sizeof(ev->buf),0); eventdel(g_efd,ev); if(len > 0) { ev->len = len; ev->buf[len] = 0; printf("C[%d]:%s\n",fd,ev->buf); eventset(ev,fd,senddata,ev); eventadd(g_efd,EPOLLOUT,ev); } else if(len == 0) { close(ev->fd) ; printf("[fd = %d] pos[%ld],close\n",fd,ev-g_events); } else { close(ev->fd) ; printf("recv[fd=%d] error[%d]:%s\n",fd,errno,strerror(errno)); } return; } void senddata(int fd,int events,void *arg) { struct myevent_s *ev = (struct myevent_s *)arg; int len; len = send(fd,ev->buf,ev->len,0); if(len > 0) { printf("send[fd=%d],[%d]%s\n",fd,len,ev->buf) ; eventdel(g_efd,ev); eventset(ev,fd,recvdata,ev); eventadd(g_efd,EPOLLIN,ev); } else { close(ev->fd) ; eventdel(g_efd,ev); printf("send[fd=%d] error %s\n",fd,strerror(errno)); } return; } void initlistensocket(int efd,short port) { int lfd = socket(AF_INET,SOCK_STREAM,0); fcntl(lfd,F_SETFL,O_NONBLOCK); eventset(&g_events[MAX_EVENTS],lfd,acceptconn,&g_events[MAX_EVENTS]); eventadd(efd,EPOLLIN,&g_events[MAX_EVENTS]); struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); sin.sin_addr.s_addr = INADDR_ANY; sin.sin_family = AF_INET; sin.sin_port = htons(port); bind(lfd,(struct sockaddr*)&sin,sizeof(sin)); listen(lfd,20); return ; } int main(int argc, char *argv[]) { unsigned short port = SERV_PORT; if(argc == 2) { port = atoi(argv[1]) ; } g_efd = epoll_create(MAX_EVENTS+1); if(g_efd <= 0) { printf("Create efd in %s error %s\n", __func__,strerror(errno)) ; } initlistensocket(g_efd,port); struct epoll_event events[MAX_EVENTS+1]; printf("server running:port[%d]\n",port); int checkpos = 0,i; while(1) { long now = time(NULL) ; for(i = 0 ; i < 100; i++,checkpos++) { if(checkpos == MAX_EVENTS) checkpos = 0; if(g_events[checkpos].status != 1) { continue; } long duration = now - g_events[checkpos].last_active; if(duration >= 60) { close(g_events[checkpos].fd) ; printf("[fd=%d] timeout\n",g_events[checkpos].fd); eventdel(g_efd,&g_events[checkpos]); } } int nfd = epoll_wait(g_efd,events,MAX_EVENTS+1,1000); if(nfd < 0) { printf("epoll_wait error, exit\n") ; break; } for(i = 0; i < nfd; i++) { struct myevent_s *ev = (struct myevent_s *)events[i].data.ptr; if((events[i].events & EPOLLIN) && (ev->events & EPOLLIN)) { ev->call_back(ev->fd,events[i].events,ev->arg) ; } if((events[i].events & EPOLLOUT) && (ev->events & EPOLLOUT)) { ev->call_back(ev->fd,events[i].events,ev->arg); } } } return 0; }
来源:博客园
作者:王清河
链接:https://www.cnblogs.com/wanghao-boke/p/11443231.html