- #pragma once
- #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"
- #ifndef EPOLL_SIZE
- #define EPOLL_SIZE 4096
- #define EPOLL_CONTEXT_SIZE (4096+256)
- #endif
- typedef void * EPollerContext;
- class Epoller
- {
- public:
- Epoller(){}
- virtual ~Epoller(){}
- bool create()
- {
- memset(_contexts,0,sizeof(_contexts));
- _handle=epoll_create(EPOLL_SIZE);
- if(_handle==-1)
- {
- glog.log(__FUNCTION__,"Epoll create error,errno is %d",errno);
- return false;
- }
- else
- return true;
- }
- void handle_events()
- {
- for(int i=0;i<_lastntfd;i++)
- {
- on_event(_events[i].data.fd,_events[i].events);
- }
- }
- int get_online_users()
- {
- int result=0;
- for(int i=0;i<EPOLL_CONTEXT_SIZE;i++)
- {
- if(_contexts[i]!=0)
- result++;
- }
- return result;
- }
- public:
- bool add(int fd,unsigned int events)
- {
- epoll_event polevt;
- polevt.events=events;
- polevt.data.fd=fd;
- return ctl(EPOLL_CTL_ADD,fd,polevt)==0;
- }
- bool del(int fd,unsigned int events)
- {
- epoll_event polevt;
- polevt.events=events;
- polevt.data.fd=fd;
- return ctl(EPOLL_CTL_DEL,fd,polevt)==0;
- }
- bool modify(int fd,unsigned int events)
- {
- epoll_event polevt;
- polevt.events=events;
- polevt.data.fd=fd;
- return ctl(EPOLL_CTL_MOD,fd,polevt)==0;
- }
- int poll(int timeout=5000)
- {
- _lastntfd=epoll_wait(_handle,_events,EPOLL_SIZE,timeout);
- return _lastntfd;
- }
- protected:
- int ctl(int op, int fd, struct epoll_event &event)
- {
- int ret=epoll_ctl(_handle,op,fd,&event);
- if(ret!=0)
- {
- glog.log(__FUNCTION__,"epoll_ctl fail,op is %d,fd is %d,errno is %d",op,fd,errno);
- }
- return ret;
- }
- protected:
- static bool setnonblocking(int sock)
- {
- int opts;
- 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__,"setnoblock error");
- return false;
- }
- else
- return true;
- }
- static bool setreuseport(int sock)
- {
- int on=1;
- int ret=setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(int));
- return ret!=-1;
- }
- protected:
- virtual void on_event(int fd,int events){}
- private:
- int _handle;
- epoll_event _events[EPOLL_SIZE];
- int _lastntfd;
- protected:
- EPollerContext _contexts[EPOLL_CONTEXT_SIZE];
- EPollerContext get_context(int value)
- {
- return _contexts[value];
- }
- bool set_context(int value,EPollerContext context)
- {
- _contexts[value]=context;
- }
- };
- class ExampleServer : public Epoller
- {
- public:
- bool init();
- void fini();
- void check_timeout();
- protected:
- void on_event(int fd,int events);
- private:
- void add_newsock(int sockvalue);
- void remove_sock(int sockvalue);
- private:
- int _listen_handler;
- };
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include "server.h"
- #include "clientmanager.h"
- bool ExampleServer::init()
- {
- this->create();
- _listen_handler=socket(AF_INET,SOCK_STREAM,0);
- setnonblocking(_listen_handler);
- setreuseport(_listen_handler);
- sockaddr_in serveraddr;
- 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);
- }
- void ExampleServer::fini()
- {
- close(_listen_handler);
- }
- void ExampleServer::add_newsock(int sockvalue)
- {
- if(sockvalue>EPOLL_CONTEXT_SIZE)
- {
- glog.log(__FUNCTION__,"newsock is %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);
- }
- }
- void ExampleServer::remove_sock(int sockvalue)
- {
- this->del(sockvalue,0);
- close(sockvalue);
- ClientSession *client=(ClientSession *)this->get_context(sockvalue);
- if(client)
- {
- gClientManager.release_client(client);
- }
- this->set_context(sockvalue,0);
- }
- void ExampleServer::on_event(int fd,int events)
- {
- if(fd==_listen_handler)
- {
- sockaddr_in sa;
- memset(&sa,0,sizeof(sa));
- socklen_t salen=sizeof(sa);
- int newsock=accept(_listen_handler,(sockaddr *)&sa,&salen);
- if(newsock>0)
- {
- add_newsock(newsock);
- }
- }
- else
- {
- ClientSession *client=(ClientSession *)this->get_context(fd);
- if(client!=NULL)
- {
- int newevents=client->handle_events(fd,events);
- if(newevents==0)
- {
- remove_sock(fd);
- }
- else
- this->modify(fd,newevents);
- }
- }
- }
- void ExampleServer::check_timeout()
- {
- unsigned int curtime=time(NULL);
- for(int i=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);
- }
- }
- }
- }
封装的EPOLL 模型
最新推荐文章于 2023-08-03 16:28:54 发布
该博客介绍了如何封装EPOLL模型,包括创建、添加、删除和修改事件监听。通过Epoller类展示了EPOLL在服务器中的应用,如监听新连接、处理客户端事件,并实现了检查超时连接的功能。
摘要由CSDN通过智能技术生成