[转]一个关于epoll的例子

来源:互联网 发布:ubuntu主题包下载 编辑:程序博客网 时间:2024/05/21 10:22
#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <cstdio>#include <errno.h>#include <iostream>#include <cstring>using namespace std;#define MAX_EVENTS 500struct myevent_s{int fd;void (*call_back)(int fd, int events, void *arg);int events;void *arg;int status; //1:in epoll wait list. 0:not inchar buff[128]; //recv data bufferint len;int s_offset;long last_active; //last active time};//set eventvoid EventSet(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;bzero(ev->buff, sizeof(ev->buff));ev->s_offset = 0;ev->len = 0;ev->last_active = time(NULL);}//add/mod event to epollvoid EventAdd(int epollFd, int events, myevent_s *ev){struct epoll_event epv;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(epollFd, op, ev->fd, &epv) < 0){perror("");}}void EventDel(int epollFd, myevent_s *ev){struct epoll_event epv;if (ev->status != 1){return ;}epv.data.ptr = ev;ev->status = 0;epoll_ctl(epollFd, EPOLL_CTL_DEL, ev->fd, &epv);}//int g_epollFd;myevent_s g_events[MAX_EVENTS + 1]; //g_events[MAX_EVENTS] is used by listen fd.void RecvData(int fd, int events, void *arg);void SendData(int fd, int events, void *arg);//accept new connections from clientsvoid AcceptConn(int fd, int events, void *arg){struct sockaddr_in sin;socklen_t len = sizeof(sin);int nfd, i;if ((nfd = accept(fd, (struct sockaddr *)&sin, &len)) == -1){if (errno != EAGAIN && errno != EINTR){//??}perror("");return ;}do{for (i=0; i<MAX_EVENTS; i++){if (g_events[i].status == 0){break;}}if (i == MAX_EVENTS){close(nfd);cout << "max connection limit" << endl;break;}        //set nonblocking        int iret = 0;        if ((iret = fcntl(nfd, F_SETFL, O_NONBLOCK)) < 0)        {            perror("");            break;        }        //add a read event for receive data        EventSet(&g_events[i], nfd, RecvData, &g_events[i]);        EventAdd(g_epollFd, EPOLLIN, &g_events[i]);} while (0);cout << "new connection" << endl;}void RecvData(int fd, int events, void *arg){struct myevent_s *ev = (struct myevent_s *)arg;int len;len = recv(fd, ev->buff + ev->len, sizeof(ev->buff)-1-ev->len, 0);EventDel(g_epollFd, ev);if (len > 0){ev->len += len;ev->buff[len] = '\0';cout << fd << ends << ev->buff << endl;EventSet(ev, fd, SendData, ev);EventAdd(g_epollFd, EPOLLOUT, ev);}else if (len == 0){close(ev->fd);cout << "closed gracefully" << endl;}else{close(ev->fd);perror("");}}//send datavoid SendData(int fd, int events, void *arg){struct myevent_s *ev = (struct myevent_s *)arg;int len;len = send(fd, ev->buff + ev->s_offset, ev->len - ev->s_offset, 0);if (len > 0){ev->s_offset += len;if (ev->s_offset == ev->len){EventDel(g_epollFd, ev);EventSet(ev, fd, RecvData, ev);EventAdd(g_epollFd, EPOLLIN, ev);}}else{close(ev->fd);EventDel(g_epollFd, ev);perror("");}}void InitListenSocket(int epollFd, short port){int listenFd = socket(AF_INET, SOCK_STREAM, 0);fcntl(listenFd, F_SETFL, O_NONBLOCK); //set non-blockingcout << "server listen fd=" << listenFd << endl;EventSet(&g_events[MAX_EVENTS], listenFd, AcceptConn, &g_events[MAX_EVENTS]);//add listen socketEventAdd(epollFd, EPOLLIN, &g_events[MAX_EVENTS]);//bind & listensockaddr_in sin;bzero(&sin, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(port);sin.sin_addr.s_addr = htonl(INADDR_ANY);bind(listenFd, (struct sockaddr *)&sin, sizeof(sin));listen(listenFd, 5);}int main(int argc, char **argv){unsigned short port = 12345; //default portg_epollFd = epoll_create(MAX_EVENTS);if (g_epollFd <= 0){perror("");exit(0);}//create & bind listen socket, and add to epoll, set non-blockingInitListenSocket(g_epollFd, port);//event loopstruct epoll_event events[MAX_EVENTS];cout << "server running..." << endl;int checkPos = 0;while (true){//a simple timeout check here, every time 100, better to use a miniheap, and add//timer eventlong now = time(NULL);for (int i=0; i<100; i++, checkPos++) //dosen't check listen fd{if (checkPos ==MAX_EVENTS){//recyclecheckPos = 0;}if (g_events[checkPos].status != 1){continue;}long duration = now = g_events[checkPos].last_active;if (duration >= 60) //60s timeout{close(g_events[checkPos].fd);cout << "timeout" << endl;EventDel(g_epollFd, &g_events[checkPos]);}}//wait for events to happenint fds = epoll_wait(g_epollFd, events, MAX_EVENTS, 100);if (fds < 0){perror("");exit(0);}for (int i=0; i<fds; i++){myevent_s *ev = (struct myevent_s *)events[i].data.ptr;//read eventif ((events[i].events & EPOLLIN) && (ev->events && EPOLLIN)){ev->call_back(ev->fd, events[i].events, ev->arg);}//write eventif ((events[i].events & EPOLLOUT) && (ev->events & EPOLLOUT)){ev->call_back(ev->fd, events[i].events, ev->arg);}}}//free resourcereturn 0;}

0 0
原创粉丝点击