织梦CMS - 轻松建站从此开始!

罗索

SevenCat 封装的EPOLL 模型

罗索客 发布于 2007-08-27 17:25 点击:次 
SevenCat 封装的EPOLL 模型。先贴这,改天加上注释。
TAG:


#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);
}
}
}
}

(iwgh)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/200708/6770.html]
本文出处:网络博客 作者:iwgh
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容