Chinaunix首页 | 论坛 | 博客
  • 博客访问: 848117
  • 博文数量: 756
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:40
文章分类

全部博文(756)

文章存档

2011年(1)

2008年(755)

我的朋友

分类:

2008-10-13 16:12:05

#pragma once
#include
#include
#include
#include
#include
#include
#include
#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  {
   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
#include
#include
#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 {
  ClientSession *client=(ClientSession *)this->get_context(i);
  if(client!=NULL)
  {
   if(curtime-client->get_last_io_time()>ITEMINDEX_SERVER_MAX_TIMEOUT)
   {
    remove_sock(i);
   }
  }
 }
}


--------------------next---------------------

阅读(446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~