javaee论坛

普通会员

225648

帖子

346

回复

360

积分

楼主
发表于 2017-06-18 17:16:51 | 查看: 140 | 回复: 0
最近比较忙,好久没更新了;今天我们看一下事件的监听方式,在linux下面事件的监听方式有三种select、poll、epoll,性能上面epoll最高,如果仅是最多监听十多个描述符,用啥无所谓,如果是几千个呢就非epoll不能胜任了。

对三种时间监听方式进行封装,由于行为相似因此都继承于一个抽象基类EventDispatcher;SelectDispatcher:使用select方式监听,PollDispatcher:使用poll方式监听,EpollDispatcher:使用epoll方式监听。

< class="cpp" name="code">/******************************************************************************************************************************************************************************** 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_*/


下面是实现文件:

< class="html" name="code">#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。


您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017