- #pragmaonce
- #include<errno.h>
- #include<sys/epoll.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<fcntl.h>
- #include<unistd.h>
- #include<string.h>
- #include"log.h"
- #ifndefEPOLL_SIZE
- #defineEPOLL_SIZE4096
- #defineEPOLL_CONTEXT_SIZE(4096+256)
- #endif
- typedefvoid*EPollerContext;
- classEpoller
- {
- public:
- Epoller(){}
- virtual~Epoller(){}
- boolcreate()
- {
- memset(_contexts,0,sizeof(_contexts));
- _handle=epoll_create(EPOLL_SIZE);
- if(_handle==-1)
- {
- glog.log(__FUNCTION__,"Epollcreateerror,errnois%d",errno);
- returnfalse;
- }
- else
- returntrue;
- }
- voidhandle_events()
- {
- for(inti=0;i<_lastntfd;i++)
- {
- on_event(_events[i].data.fd,_events[i].events);
- }
- }
- intget_online_users()
- {
- intresult=0;
- for(inti=0;i<EPOLL_CONTEXT_SIZE;i++)
- {
- if(_contexts[i]!=0)
- result++;
- }
- returnresult;
- }
- public:
- booladd(intfd,unsignedintevents)
- {
- epoll_eventpolevt;
- polevt.events=events;
- polevt.data.fd=fd;
- returnctl(EPOLL_CTL_ADD,fd,polevt)==0;
- }
- booldel(intfd,unsignedintevents)
- {
- epoll_eventpolevt;
- polevt.events=events;
- polevt.data.fd=fd;
- returnctl(EPOLL_CTL_DEL,fd,polevt)==0;
- }
- boolmodify(intfd,unsignedintevents)
- {
- epoll_eventpolevt;
- polevt.events=events;
- polevt.data.fd=fd;
- returnctl(EPOLL_CTL_MOD,fd,polevt)==0;
- }
- intpoll(inttimeout=5000)
- {
- _lastntfd=epoll_wait(_handle,_events,EPOLL_SIZE,timeout);
- return_lastntfd;
- }
- protected:
- intctl(intop,intfd,structepoll_event&event)
- {
- intret=epoll_ctl(_handle,op,fd,&event);
- if(ret!=0)
- {
- glog.log(__FUNCTION__,"epoll_ctlfail,opis%d,fdis%d,errnois%d",op,fd,errno);
- }
- returnret;
- }
- protected:
- staticboolsetnonblocking(intsock)
- {
- intopts;
- opts=fcntl(sock,F_GETFL);
- if(opts<0)
- opts=O_NONBLOCK;
- else
- opts=opts|O_NONBLOCK;
- if(fcntl(sock,F_SETFL,opts)<0)
- {
- glog.log(__FUNCTION__,"setnoblockerror");
- returnfalse;
- }
- else
- returntrue;
- }
- staticboolsetreuseport(intsock)
- {
- inton=1;
- intret=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(int));
- returnret!=-1;
- }
- protected:
- virtualvoidon_event(intfd,intevents){}
- private:
- int_handle;
- epoll_event_events[EPOLL_SIZE];
- int_lastntfd;
- protected:
- EPollerContext_contexts[EPOLL_CONTEXT_SIZE];
- EPollerContextget_context(intvalue)
- {
- return_contexts[value];
- }
- boolset_context(intvalue,EPollerContextcontext)
- {
- _contexts[value]=context;
- }
- };
- classExampleServer:publicEpoller
- {
- public:
- boolinit();
- voidfini();
- voidcheck_timeout();
- protected:
- voidon_event(intfd,intevents);
- private:
- voidadd_newsock(intsockvalue);
- voidremove_sock(intsockvalue);
- private:
- int_listen_handler;
- };
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include"server.h"
- #include"clientmanager.h"
- boolExampleServer::init()
- {
- this->create();
- _listen_handler=socket(AF_INET,SOCK_STREAM,0);
- setnonblocking(_listen_handler);
- setreuseport(_listen_handler);
- sockaddr_inserveraddr;
- memset(&serveraddr,0,sizeof(serveraddr));
- serveraddr.sin_family=AF_INET;
- serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
- serveraddr.sin_port=htons(ITEMLIST_SERVER_PORT);
- bind(_listen_handler,(sockaddr*)&serveraddr,sizeof(serveraddr));
- listen(_listen_handler,ITEMCOMMENT_SERVER_LISTEN_BACKLOG);
- this->add(_listen_handler,EPOLLIN|EPOLLOUT);
- this->set_context(_listen_handler,0);
- }
- voidExampleServer::fini()
- {
- close(_listen_handler);
- }
- voidExampleServer::add_newsock(intsockvalue)
- {
- if(sockvalue>EPOLL_CONTEXT_SIZE)
- {
- glog.log(__FUNCTION__,"newsockis%d,>%d",sockvalue,EPOLL_CONTEXT_SIZE);
- close(sockvalue);
- return;
- }
- ClientSession*newsession=gClientManager.alloc_client_session(sockvalue);
- if(newsession==NULL)
- {
- close(sockvalue);
- return;
- }
- if(add(sockvalue,EPOLLIN|EPOLLOUT))
- {
- this->set_context(sockvalue,newsession);
- }
- else
- {
- gClientManager.release_client(newsession);
- close(sockvalue);
- }
- }
- voidExampleServer::remove_sock(intsockvalue)
- {
- this->del(sockvalue,0);
- close(sockvalue);
- ClientSession*client=(ClientSession*)this->get_context(sockvalue);
- if(client)
- {
- gClientManager.release_client(client);
- }
- this->set_context(sockvalue,0);
- }
- voidExampleServer::on_event(intfd,intevents)
- {
- if(fd==_listen_handler)
- {
- sockaddr_insa;
- memset(&sa,0,sizeof(sa));
- socklen_tsalen=sizeof(sa);
- intnewsock=accept(_listen_handler,(sockaddr*)&sa,&salen);
- if(newsock>0)
- {
- add_newsock(newsock);
- }
- }
- else
- {
- ClientSession*client=(ClientSession*)this->get_context(fd);
- if(client!=NULL)
- {
- intnewevents=client->handle_events(fd,events);
- if(newevents==0)
- {
- remove_sock(fd);
- }
- else
- this->modify(fd,newevents);
- }
- }
- }
- voidExampleServer::check_timeout()
- {
- unsignedintcurtime=time(NULL);
- for(inti=0;i<EPOLL_SIZE+256;i++)
- {
- ClientSession*client=(ClientSession*)this->get_context(i);
- if(client!=NULL)
- {
- if(curtime-client->get_last_io_time()>ITEMINDEX_SERVER_MAX_TIMEOUT)
- {
- remove_sock(i);
- }
- }
- }
- }