Epoll类
#ifndef __CLIENT_EPOLL_H__ #define __CLIENT_EPOLL_H__ //#include "cocos2d.h" #include "ClientSocket.h" #ifdef WIN32 #include <winsock.h> #else #include <sys/epoll.h> #include <pthread.h> #endif //USING_NS_CC; #define _SOCKET_FD_MAX_ 3 #define EVENTMAX (_SOCKET_FD_MAX_*3) typedef void (*MY_SOCKET_FD_CALLBACK)(int event,void* buf,int len); class CMyEpoll { public: CMyEpoll(); ~CMyEpoll(); public: int MyCreateEpoll(void); int MyAddSocketFdEvent(int socket_fd, MY_SOCKET_FD_CALLBACK cb); int MyDelSocketFdEvent(int socket_fd); void RunThread(void); void MyRun(float time); MY_SOCKET_FD_CALLBACK MyGetSocketFdCallBack(int socket_fd); public: static bool m_exitflag; static int m_socket_fd[_SOCKET_FD_MAX_]; static MY_SOCKET_FD_CALLBACK m_cb[_SOCKET_FD_MAX_]; #ifdef WIN32 static bool socketConnect[_SOCKET_FD_MAX_]; #endif int m_epfd; }; #endif
#include "ClientEpoll.h" bool CMyEpoll::m_exitflag = false; int CMyEpoll::m_socket_fd[_SOCKET_FD_MAX_] = {0}; MY_SOCKET_FD_CALLBACK CMyEpoll::m_cb[_SOCKET_FD_MAX_] ={0}; #ifdef WIN32 bool CMyEpoll::socketConnect[_SOCKET_FD_MAX_] = {0}; #endif CMyEpoll::CMyEpoll() { m_epfd = -1; for( int i = 0; i < _SOCKET_FD_MAX_; i++ ) { CMyEpoll::m_socket_fd[i] = -1; CMyEpoll::m_cb[i] = NULL; } CMyEpoll::m_exitflag = false; } CMyEpoll::~CMyEpoll() { CMyEpoll::m_exitflag = true; #ifdef WIN32 #else if( m_epfd >= 0 ) { close( m_epfd ); m_epfd = -1; } #endif } //创建socket int CMyEpoll::MyCreateEpoll(void) { #ifdef WIN32 return 0; #else /* 该 函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间, 用来存放你想关注的socket fd上是否发生以及发生了什么事件。 size就是你在这个epoll fd上能关注的最大socket fd数。随你定好了。只要你有空间。 */ m_epfd = epoll_create(1024); if( m_epfd == -1 ) { return -1; } return m_epfd; #endif } //handle: sockid //cb : socket callback fun int CMyEpoll::MyAddSocketFdEvent(int socket_fd, MY_SOCKET_FD_CALLBACK cb) { for( int i = 0; i < _SOCKET_FD_MAX_; i++ ) { if( CMyEpoll::m_socket_fd[i] == -1 ) // { CMyEpoll::m_socket_fd[i] = socket_fd; CMyEpoll::m_cb[i] = cb; #ifdef WIN32 CMyEpoll::socketConnect[i] = false; #endif break; } } #ifdef WIN32 return 0; #else struct epoll_event event = {0}; event.data.fd = socket_fd; event.events = (EPOLLIN | EPOLLOUT); /* 该函数用于控制某个epoll文件描述符上的事件, 可以注册事件,修改事件,删除事件 */ int nRet = epoll_ctl (m_epfd, EPOLL_CTL_ADD, socket_fd, &event); if (nRet == -1) { return -1; } return 0; #endif } //handle: sockid //cb : socket callback fun int CMyEpoll::MyDelSocketFdEvent(int socket_fd) { for( int i = 0; i < _SOCKET_FD_MAX_; i++ ) { if( CMyEpoll::m_socket_fd[i] == socket_fd ) { CMyEpoll::m_socket_fd[i] = -1; CMyEpoll::m_cb[i] = NULL; } } return 0; #ifdef WIN32 #else struct epoll_event event = {0}; event.data.fd = socket_fd; event.events = EPOLLIN; int nRet = epoll_ctl (m_epfd, EPOLL_CTL_DEL, socket_fd, &event); if (nRet == -1) { return -1; } return 0; #endif } MY_SOCKET_FD_CALLBACK CMyEpoll::MyGetSocketFdCallBack(int socket_fd) { for( int i = 0; i < _SOCKET_FD_MAX_; i++ ) { if( CMyEpoll::m_socket_fd[i] == socket_fd ) { return CMyEpoll::m_cb[i]; } } return NULL; } #define PROCESS_DATA_LEN (4*1024) static char data[PROCESS_DATA_LEN] = {0}; #ifdef WIN32 void CMyEpoll::RunThread( void ) { fd_set fdread; fd_set fdwrite; struct timeval tv = {0,20}; //while(1) { if(CMyEpoll::m_exitflag ) return ; FD_ZERO(&fdread); FD_ZERO(&fdwrite); for( int i = 0; i < _SOCKET_FD_MAX_; i++ ) { if(CMyEpoll::m_socket_fd[i] != -1) { FD_SET(CMyEpoll::m_socket_fd[i], &fdread); FD_SET(CMyEpoll::m_socket_fd[i], &fdwrite); } } switch(select(0, &fdread, &fdwrite, NULL, &tv)) { case 0: break; default: for( int i = 0; i < _SOCKET_FD_MAX_; i++ ) { if(CMyEpoll::m_socket_fd[i] != -1) { if(FD_ISSET(CMyEpoll::m_socket_fd[i],&fdread)) { char data[PROCESS_DATA_LEN] = {0}; int count = recv(CMyEpoll::m_socket_fd[i], (char*)data, PROCESS_DATA_LEN, 0); if(CMyEpoll::m_cb[i] && count > 0) CMyEpoll::m_cb[i]( EVENT_READ, data, count ); } if(!CMyEpoll::socketConnect[i] && FD_ISSET(CMyEpoll::m_socket_fd[i],&fdwrite)) { CMyEpoll::socketConnect[i] = true; if(CMyEpoll::m_cb[i]) CMyEpoll::m_cb[i]( EVENT_CONNECTED, NULL, 0 ); } } } break; } } return ; } #else void CMyEpoll::RunThread( void ) { int count = 0; int socket_fd; int eventnum = 0; int loop = 0; struct epoll_event allEvents[EVENTMAX] = {0}; MY_SOCKET_FD_CALLBACK pfun = NULL; CMyEpoll *pmyepoll = (CMyEpoll *)this; //主循环 //while(1) { if( CMyEpoll::m_exitflag ) { //pthread_exit((void*)& "exit MyRun" ); return ; } eventnum = 0; loop = 0; memset( allEvents, 0, sizeof(allEvents) ); //等待事件 eventnum = epoll_wait (pmyepoll->m_epfd, allEvents, EVENTMAX, 0 ); for( loop = 0; loop < eventnum; loop++ ) { socket_fd = allEvents[loop].data.fd; pfun = pmyepoll->MyGetSocketFdCallBack( socket_fd ); //处理连接事件 //连接成功 if( allEvents[loop].events == EPOLLOUT ) { struct epoll_event event = {0}; event.data.fd = socket_fd; event.events = (EPOLLIN); epoll_ctl (pmyepoll->m_epfd, EPOLL_CTL_MOD, socket_fd, &event); if( pfun ) { pfun( EVENT_CONNECTED, NULL, 0 ); continue; } } //连接失败 if( allEvents[loop].events == (EPOLLIN | EPOLLERR | EPOLLHUP) ) { if( pfun ) { pfun( EVENT_CONNECT_ERROR, NULL, 0 ); pmyepoll->MyDelSocketFdEvent( socket_fd ); continue; } } //发生错误 if ( (allEvents[loop].events & EPOLLERR) || (allEvents[loop].events & EPOLLHUP) ) { if( pfun ) { pfun( EVENT_ERROR, NULL, 0 ); pmyepoll->MyDelSocketFdEvent( socket_fd ); continue; } } //循环接收数据 if( allEvents[loop].events & EPOLLIN ) { while( 1 ) { count = recv( socket_fd, data, PROCESS_DATA_LEN, 0 ); if( count < 0 ) { if( errno != EAGAIN ) { //通知应用 if( pfun ) { pfun( EVENT_ERROR, NULL, 0 ); } pmyepoll->MyDelSocketFdEvent( socket_fd ); } break; } else if( count == 0 ) { //通知应用 if( pfun ) { pfun( EVENT_READ_ERROR, NULL, 0 ); } pmyepoll->MyDelSocketFdEvent( socket_fd ); break; } else { if( pfun ) { pfun( EVENT_READ, data, count ); } if( count < PROCESS_DATA_LEN ) { break; } } } } } } return ; } #endif