转:sock_ev——linux平台socket事件框架(event dispatcher) .
最近比较忙,好久没更新了;今天我们看一下事件的监听方式,在linux下面事件的监听方式有三种select、poll、epoll,性能上面epoll最高,如果仅是最多监听十多个描述符,用啥无所谓,如果是几千个呢就非epoll不能胜任了。
对三种时间监听方式进行封装,由于行为相似因此都继承于一个抽象基类EventDispatcher;SelectDispatcher:使用select方式监听,PollDispatcher:使用poll方式监听,EpollDispatcher:使用epoll方式监听。
/***************************************************************************************
****************************************************************************************
* FILE : event_dispatcher.h
* Description :
*
* Copyright (c) 2012 by Liu Yanyun(E-mail:liuyun827@foxmail.com). All Rights Reserved.
* Without permission, shall not be used for any commercial purpose
*
* History:
* Version Name Date Description
0.1 Liu Yanyun 2012/12/20 Initial Version
****************************************************************************************
****************************************************************************************/
#ifndef _EVENT_DISPATCHER_H_
#define _EVENT_DISPATCHER_H_
#include <map>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sock_ev.h"
#include "event_loop.h"
class Socket;
class EventLoop;
typedef std::vector<struct pollfd> PollFdVecT;
/*==================================================================
* Function : EventDispatcher
* Description : event dispatcher base class
==================================================================*/
class EventDispatcher
{
public:
/*==================================================================
* Function : EventDispatcher.EventDispatcher
* Description : construction function
==================================================================*/
EventDispatcher();
/*==================================================================
* Function : EventDispatcher.~EventDispatcher
* Description : Destructor function
==================================================================*/
virtual ~EventDispatcher();
/*==================================================================
* Function : EventDispatcher.initialize
* Description : implement by subclass
* Return Value: initialize success return true,or else return false
==================================================================*/
virtual bool initialize() = 0;
/*==================================================================
* Function : EventDispatcher.addEvt
* Description : add an event and register callback
* Input Para :
* Output Para :
* Return Value: success return true,or else return false
==================================================================*/
virtual bool addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_) = 0;
/*==================================================================
* Function : EventDispatcher.removeEvt
* Description : remove an event and un-register callback
* Input Para :
* Output Para :
* Return Value: success return true,or else return false
==================================================================*/
virtual bool removeEvt(Socket *sock_,
EventType evt_) = 0;
/*==================================================================
* Function : EventDispatcher.listen
* Description : wait for event trigger
* Input Para :
* Output Para :
* Return Value:
==================================================================*/
virtual int listen(SockMapT &sockMap_,
int timeout_) = 0;
};
/*==================================================================
* Function : SelectDispatcher
* Description : use select for wait event
==================================================================*/
class SelectDispatcher : public EventDispatcher
{
public:
/*==================================================================
* Function : SelectDispatcher.SelectDispatcher
* Description : construction function
==================================================================*/
SelectDispatcher();
/*==================================================================
* Function : SelectDispatcher.~SelectDispatcher
* Description : Destructor function
==================================================================*/
virtual ~SelectDispatcher();
/*==================================================================
* Function : initialize
* Description : Please reference to parent class
==================================================================*/
bool initialize();
/*==================================================================
* Function : addEvt
* Description : Please reference to parent class
==================================================================*/
bool addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_);
/*==================================================================
* Function : removeEvt
* Description : Please reference to parent class
==================================================================*/
bool removeEvt(Socket *sock_,
EventType evt_);
/*==================================================================
* Function : listen
* Description : Please reference to parent class
==================================================================*/
int listen(SockMapT &sockMap_,
int timeout_);
private:
fd_set readSet;
fd_set writeSet;
fd_set exceptSet;
};
/*==================================================================
* Function : PollDispatcher
* Description : use poll for wait event
==================================================================*/
class PollDispatcher : public EventDispatcher
{
public:
/*==================================================================
* Function : PollDispatcher.PollDispatcher
* Description : construction function
==================================================================*/
PollDispatcher();
/*==================================================================
* Function : PollDispatcher.~PollDispatcher
* Description : Destructor function
==================================================================*/
virtual ~PollDispatcher();
/*==================================================================
* Function : PollDispatcher.getPos
* Description : get position in the vector by fd
* Input Para : socket fd
* Return Value: position in the vector
==================================================================*/
PollFdVecT::iterator getPos(int fd_);
/*==================================================================
* Function : initialize
* Description : Please reference to parent class
==================================================================*/
bool initialize();
/*==================================================================
* Function : addEvt
* Description : Please reference to parent class
==================================================================*/
bool addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_);
/*==================================================================
* Function : removeEvt
* Description : Please reference to parent class
==================================================================*/
bool removeEvt(Socket *sock_,
EventType evt_);
/*==================================================================
* Function : listen
* Description : Please reference to parent class
==================================================================*/
int listen(SockMapT &sockMap_,
int timeout_);
private:
PollFdVecT pollFds;
};
/*==================================================================
* Function : EpollDispatcher
* Description : use epoll for wait event
==================================================================*/
class EpollDispatcher : public EventDispatcher
{
public:
/*==================================================================
* Function : EpollDispatcher.EpollDispatcher
* Description : construction function
==================================================================*/
EpollDispatcher();
/*==================================================================
* Function : EpollDispatcher.~EpollDispatcher
* Description : Destructor function
==================================================================*/
virtual ~EpollDispatcher();
/*==================================================================
* Function : initialize
* Description : Please reference to parent class
==================================================================*/
bool initialize();
/*==================================================================
* Function : addEvt
* Description : Please reference to parent class
==================================================================*/
bool addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_);
/*==================================================================
* Function : removeEvt
* Description : Please reference to parent class
==================================================================*/
bool removeEvt(Socket *sock_,
EventType evt_);
/*==================================================================
* Function : listen
* Description : Please reference to parent class
==================================================================*/
int listen(SockMapT &sockMap_,
int timeout_);
private:
int epollFd;
};
#endif /*_EVENT_DISPATCHER_H_*/
下面是实现文件:
#include "socket.h"
#include "event_dispatcher.h"
#include "sock_ev.h"
#include <errno.h>
EventDispatcher::EventDispatcher()
{
//do nothing
}
EventDispatcher::~EventDispatcher()
{
//do nothing
}
SelectDispatcher::SelectDispatcher()
{
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_ZERO(&exceptSet);
}
SelectDispatcher::~SelectDispatcher()
{
}
bool SelectDispatcher::initialize()
{
return true;
}
bool SelectDispatcher::addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_)
{
if(evt_ & evRead)
{
FD_SET(sock_->getFd(), &readSet);
}
if(evt_ & evWrite)
{
FD_SET(sock_->getFd(), &writeSet);
}
if(evt_ & evError)
{
FD_SET(sock_->getFd(), &exceptSet);
}
sock_->setCallBack(loop_, cb_, evt_, arg_);
return true;
}
bool SelectDispatcher::removeEvt(Socket *sock_,
EventType evt_)
{
sock_->clearCallBack(evt_);
if(evt_ & evRead)
{
FD_CLR(sock_->getFd(), &readSet);
}
if(evt_ & evWrite)
{
FD_CLR(sock_->getFd(), &writeSet);
}
if(evt_ & evError)
{
FD_CLR(sock_->getFd(), &exceptSet);
}
return true;
}
int SelectDispatcher::listen(SockMapT &sockMap_,
int timeout_)
{
timeval timeout;
timeout.tv_sec = timeout_/1000;
timeout.tv_usec = timeout_ % 1000 * 1000;
fd_set tmpReadSet = readSet;
fd_set tmpWriteSet = writeSet;
int maxFd = sockMap_.rbegin()->first;
int num = select(maxFd + 1, &tmpReadSet, &tmpWriteSet, NULL,
(timeout_ >=0) ? (&timeout):NULL);
if (num <= 0)
{
logTrace("num=%d;size:%d;%m", num, sockMap_.size());
return num;
}
SockMapT::iterator it = sockMap_.begin();
while (it != sockMap_.end())
{
SockMapT::iterator tmpIt = it++;
if(FD_ISSET(tmpIt->first, &tmpReadSet))
{
tmpIt->second->processEvent(evRead);
}
if(FD_ISSET(tmpIt->first, &tmpWriteSet))
{
tmpIt->second->processEvent(evWrite);
}
}
return num;
}
PollDispatcher::PollDispatcher()
{
//do nothing
}
PollDispatcher::~PollDispatcher()
{
pollFds.clear();
}
PollFdVecT::iterator PollDispatcher::getPos(int fd_)
{
PollFdVecT::iterator it;
for(it = pollFds.begin(); it != pollFds.end(); it++)
{
if(it->fd == fd_)
{
return it;
}
}
return it;
}
bool PollDispatcher::initialize()
{
return true;
}
bool PollDispatcher::addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_)
{
struct pollfd pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sock_->getFd();
PollFdVecT::iterator it = getPos(pfd.fd);
if(it == pollFds.end())
{
if(evt_ & evRead)
{
pfd.events |= POLLIN;
}
if(evt_ & evWrite)
{
pfd.events |= POLLOUT;
}
pollFds.push_back(pfd);
}
else
{
if(evt_ & evRead)
{
it->events |= POLLIN;
}
if(evt_ & evWrite)
{
it->events |= POLLOUT;
}
}
sock_->setCallBack(loop_, cb_, evt_, arg_);
return true;
}
bool PollDispatcher::removeEvt(Socket *sock_,
EventType evt_)
{
sock_->clearCallBack(evt_);
PollFdVecT::iterator it = getPos(sock_->getFd());
if(it == pollFds.end())
{
logTrace("can't find this in poll event vector");
return false;
}
else
{
EventType evt = ~evt_&sock_->getEvt();
if(0 == evt)
{
pollFds.erase(it);
return true;
}
if(evt & evRead)
{
it->events |= POLLIN;
}
if(evt & evWrite)
{
it->events |= POLLOUT;
}
}
return true;
}
int PollDispatcher::listen(SockMapT &sockMap_,
int timeout)
{
int num = poll(&pollFds[0], pollFds.size(), timeout);
if(num <= 0)
{
logTrace("num=%d;size:%d;%m", num, sockMap_.size());
return num;
}
uint32_t index = 0;
for(index = 0; index < pollFds.size(); index++)
{
struct pollfd pfd = pollFds[index];
SockMapT::iterator mapIt = sockMap_.find(pfd.fd);
if(mapIt == sockMap_.end())
{
logTrace("can't find this fd in map");
continue;
}
if(pfd.revents & POLLIN)
{
mapIt->second->processEvent(evRead);
}
if(pfd.revents & POLLOUT)
{
mapIt->second->processEvent(evWrite);
}
}
return num;
}
EpollDispatcher::EpollDispatcher()
{
epollFd = -1;
}
/// 析构函数
EpollDispatcher::~EpollDispatcher()
{
close(epollFd);
}
bool EpollDispatcher::initialize()
{
epollFd = epoll_create(256);
if(-1 == epollFd)
{
logTrace("epoll_create failed;%m");
return false;
}
return true;
}
bool EpollDispatcher::addEvt(EventLoop *loop_,
Socket *sock_,
EvCallBack cb_,
EventType evt_,
void *arg_)
{
epoll_event epEvt;
memset(&epEvt, 0, sizeof(epEvt));
epEvt.data.fd = sock_->getFd();
EventType evt = evt_|sock_->getEvt();
if(evt & evRead)
{
epEvt.events |= EPOLLIN;
}
if (evt & evWrite)
{
epEvt.events |= EPOLLOUT;
}
if(epoll_ctl(epollFd, EPOLL_CTL_MOD, sock_->getFd(), &epEvt) != 0)
{
if(errno == ENOENT)
{
if(epoll_ctl(epollFd, EPOLL_CTL_ADD, sock_->getFd(), &epEvt) != 0)
{
logTrace("epoll_ctl(EPOLL_CTL_ADD) failed,%m");
return false;
}
}
else
{
logTrace("epoll_ctl(EPOLL_CTL_MOD) failed,%m");
return false;
}
}
sock_->setCallBack(loop_, cb_, evt_, arg_);
return true;
}
bool EpollDispatcher::removeEvt(Socket *sock_,
EventType evt_)
{
sock_->clearCallBack(evt_);
epoll_event epEvt;
if(epoll_ctl(epollFd, EPOLL_CTL_DEL, sock_->getFd(), &epEvt) != 0)
{
logTrace("epoll_ctl(EPOLL_CTL_DEL) failed,%m");
return false;
}
EventType evt = ~evt_&sock_->getEvt();
if(0 == evt)
{
return true;
}
memset(&epEvt, 0, sizeof(epEvt));
epEvt.data.fd = sock_->getFd();
if(evt & evRead)
{
epEvt.events |= EPOLLIN;
}
if (evt & evWrite)
{
epEvt.events |= EPOLLOUT;
}
if(epoll_ctl(epollFd, EPOLL_CTL_ADD, sock_->getFd(), &epEvt) != 0)
{
logTrace("epoll_ctl(EPOLL_CTL_ADD) failed,%m");
return false;
}
return true;
}
int EpollDispatcher::listen(SockMapT &sockMap_,
int timeout)
{
epoll_event epEvts[256];
int num = epoll_wait(epollFd, epEvts, 256, timeout);
if(num <= 0)
{
logTrace("num=%d;size:%d;%m", num, sockMap_.size());
return num;
}
for(int idx = 0; idx < num; ++idx)
{
int fd = epEvts[idx].data.fd;
SockMapT::iterator tmpIt = sockMap_.find(fd);
if(tmpIt == sockMap_.end())
{
logTrace("can't find this fd in map");
continue;
}
if(epEvts[idx].events & EPOLLIN)
{
tmpIt->second->processEvent(evRead);
}
if(epEvts[idx].events & EPOLLOUT)
{
tmpIt->second->processEvent(evWrite);
}
}
return num;
}
基本就是对select、poll、epoll事件监听方式的封装。
注册事件时,要提供相应的callback函数,所谓callback就是提供一个函数指针,等相应的事件触发时,就调用相应的函数进行执行,MFC中到处都是这种callback。
转:sock_ev——linux平台socket事件框架(event dispatcher) .的更多相关文章
- 转:sock_ev——linux平台socket事件框架(event loop) .
上一篇我们封装了三种事件监听方式,如果分别提供给客户端使用,有点不方便,也不利于统一管理:我们再封装一层EventLoop. /************************************ ...
- 转:sock_ev——linux平台socket事件框架(socket API的封装) .
把linux平台提供的有关socket操作的API进行封装是有必要的:基于stream操作的流程与基于dgram操作的流程略有不同,分别放在两个类中,但两者又有很多相似的操作,因此写一个基类,让其继承 ...
- 转:sock_ev——linux平台socket事件框架(基于字节流的测试程序) .
原文:http://blog.csdn.net/gdutliuyun827/article/details/8257186 由于工作与学习的需要,写了一个socket的事件处理框架,在公司写的已经使用 ...
- 转:sock_ev——linux平台socket事件框架(socket代理类) .
前面分析了对socket基本操作的封装,并按照数据的传送方式写了两个类,本篇将写一个代理类提供给库的使用者使用的类. /**************************************** ...
- 转:sock_ev——linux平台socket事件框架(uri地址的解析) .
在第一篇中,已经说明,传递的socket地址采取以下形式: [cpp] view plaincopyprint?stream://192.168.2.10:8080 dgram://192.168 ...
- 转:sock_ev——linux平台socket事件框架(基于数据报的测试程序) .
上一篇已经做过注释,这一篇直接上代码 /******************************************************************************** ...
- 转:sock_ev——linux平台socket事件框架(logTrace) .
写代码要有调试log,采用syslog的输出:一般会输出到"/var/log/messages" /**************************************** ...
- AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
- Linux平台用C++实现事件对象,同步线程
前文在Win32平台上用C++实现了事件对象Event,对线程进行同步,以达到期望目的.这次在Linux平台上实现与之类似的事件对象.与其相关的一组API包括:pthread_mutex_init,p ...
随机推荐
- bzoj1001: [BeiJing2006]狼抓兔子 -- 最小割
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Description 现在小朋友们最喜欢的"喜羊羊与灰太狼 ...
- nginx 访问第三方服务(1)
nginx提供了两种全异步方式来与第三方服务通信,分别是upstream和subrequest. upstream:nginx为代理服务器,作消息透传.将第三方服务的内容原封不动的返回给用户. sub ...
- mysql 绿色版安装
1. 下载MySql5.6.10GA解压缩版,这就不多说也不上图了,下不到或者下好之后不知道如何解压的接下去的文章也没什么好多看的. 2. 解压好之后进入根目录是这样个情况(本人使用的是MySql5. ...
- 博雅PHP高级工程师面试题-自拟
作者:元如枫 2010年 1.现有学校课程内容系统简单需求描述,试着提供解决方案. 需求简单描述如下: 1)对象及属性 学校: 学校名称,学校所属分类,学校介绍,学校地图标记,学校所属地区,标签, ...
- UnsupportedOperationException:can't convert to dimension :typx=0x1
at android.content.res.TypeArray.getDimensionPixelSize(TypeArray.java:463) 今天在给项目做适配执行项目时遇到这个错误,发生错误 ...
- 虚拟机安装Linux过程和踩坑
由于想学习node,服务器端大都使用Linux系统,所以就想着在笔记本上弄个虚拟机,装上Linux,使用xshell在window上操作也方便,也借此来熟悉一下Linux,接下来就解释下安装的步骤和遇 ...
- win7 系统装SQLServer2000 成功
昨天在win7上装SQLServer数据库,写一下体会.首先,如果以前安装的话,要删除干净.我也找了半天的网络资料.1.把原来SQLServer的安装目录 C:\Program Files\Micro ...
- Python pass 语句
Python pass 语句 Python pass是空语句,是为了保持程序结构的完整性. pass 不做任何事情,一般用做占位语句. Python 语言 pass 语句语法格式如下: pass 实例 ...
- DCI:The DCI Architecture: A New Vision of Object-Oriented Programming
SummaryObject-oriented programming was supposed to unify the perspectives of the programmer and the ...
- 仿LOL项目开发第五天
仿LOL项目开发第五天 by草帽 今天呢,我们看下能开发什么内容,首先上节我们已经讲了UI框架的搭建,上节还遗留下很多问题,比如说消息的字符是代码里面自己赋值的. 那么就比较死板,按照正常的逻辑,那些 ...