EOPLL ET 第一次写,请大神们帮忙纠错

来源:互联网 发布:事情正在起变化 知乎 编辑:程序博客网 时间:2024/05/16 19:48

#ifndefH_NETDEF_H#defineH_NETDEF_H#include<stdio.h>#include<stdint.h>#include<stdlib.h>#include<iostream>#include<string.h>#ifdef WIN32#ifndef _WIN32_WINNT#define _WIN32_WINNT 0x0500#endif#define    WIN32_LEAN_AND_MEAN#include <windows.h>#include <winsock2.h>#else#include <unistd.h>#include <errno.h>#include <limits.h>#include <stdarg.h>#include <time.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <fcntl.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <ctype.h>#include <assert.h>#include <netinet/tcp.h>#include <semaphore.h>#include <pthread.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <signal.h>#include <sys/ioctl.h>#include <linux/if.h>#include <sys/epoll.h>#include <unordered_map>#include <unordered_set>#define EWOULDBLOCKEAGAIN#define SOCKET_ERROR            (-1)#define closesocketclose#define INVALID_SOCKET(SOCKET)(~0)typedef int SOCKET;typedef int EPOLL;#endif// TCP#define DEF_READ_BUF_TCP(1460)struct S_TcpDataBuf{charm_szBuf[DEF_READ_BUF_TCP];intm_iBufLen;SOCKET m_oSocket;};struct S_TcpConnect{SOCKETm_oSocket;struct sockaddr_inm_oAddress;int64_tm_i64ConnectTime;S_TcpConnect() {m_oSocket = -1;memset((void*)&m_oAddress, 0, sizeof(struct sockaddr_in) );m_i64ConnectTime = 0;}};class ITcpNotice{public:virtual int OnConnect( SOCKET aoSocket, struct sockaddr_in& loAddr)= 0;virtual int OnClose( SOCKET aoSocket)= 0;virtual int OnRecv( SOCKET aoSocket, char* apBuf, int aiLen )= 0;};#define DEF_READ_BUF_UDP(1472)#endif // H_NETDEF_H
/*A:SnightQQ:51171107*/#ifndef H_DEF_EPOLLSVR_H#defineH_DEF_EPOLLSVR_H#include <string.h>#include <queue>#include "CCrt.h"#include "NetDef.h"#include "SocketHelper.h"class CEpollTcpSvr{public:CEpollTcpSvr( void );~CEpollTcpSvr( void );public:bool StartSvr( int aiPort , int aiTaskThreadCnt, int aiCatchSize, int aiMaxSocketCnt = 10000);bool SendData(SOCKET aoSocket, char* apBuf, int aiLen);private:void UpdateEvents( EPOLL aoEpoll, SOCKET aoSocket, int aoEvent, int aoOpt );bool OnEpollET(struct epoll_event* aoEvents, int aiNum, EPOLL aoEpoll, SOCKET aoListenFd);void OnConnect(SOCKET aoSocket, struct sockaddr_in& aoAddr);void OnCutdown(SOCKET apConnect);static void* _WorkThread(void * apThis);void WorkThread(void);static void* _CheckThread(void * apThis);void CheckThread(void);static void* _TaskThread(void * apThis);void TaskThread(void);S_TcpDataBuf*GetDataBuf( void );voidBackDataBuf(S_TcpDataBuf* apBuf );S_TcpConnect*GetConnect(void);voidBackConnect(S_TcpConnect* apBuf);private:boolm_bIsInit;intm_iSockaddrinLen;intm_iMaxSocketCnt;SOCKETm_oLsnSocket;EPOLLm_oEpollFD;pthread_tm_oWorkThread;pthread_tm_oCheckThread;pthread_t*m_pTaskThread;intm_iTaskThreadCnt;ITcpNotice*m_pTcpNotice;intm_iTotalCCnt;int64_tm_i64TotalRecvPackageCnt;doublem_dTotalRecvKByte;int64_tm_i64TotalSendPackageCnt;doublem_dTotalSendKByte;// 缓存bufstd::queue<S_TcpDataBuf*>m_oDataCatchBufQueue;std::recursive_mutexm_oDataCatchBufQueueLock;intm_iMaxCacheSize;// 任务bufstd::queue<S_TcpDataBuf*>m_oDataTaskBufQueue;std::recursive_mutexm_oDataTaskBufQueueLock;// 连接std::unordered_map< SOCKET, S_TcpConnect* >m_oConectMap;std::recursive_mutexm_oConectMapLock;// 缓存bufstd::queue<S_TcpConnect*>m_oConnectCatchQueue;std::recursive_mutexm_oConnectCatchQueueLock;};#endif //H_DEF_EPOLLSVR_H

#include "EpollTcpSvr.h"#define MAX_EVENT_NUM(6666)CEpollTcpSvr::CEpollTcpSvr(){m_pTcpNotice = NULL;m_iTotalCCnt = 0;m_i64TotalRecvPackageCnt = 0;m_dTotalRecvKByte = 0; m_i64TotalSendPackageCnt = 0;m_dTotalSendKByte = 0;m_bIsInit = false;m_iMaxCacheSize = 1000;m_iSockaddrinLen = sizeof(struct sockaddr_in);}CEpollTcpSvr::~CEpollTcpSvr(){}void CEpollTcpSvr::OnConnect(SOCKET aoSocket, struct sockaddr_in& aoAddr){if (m_pTcpNotice)  m_pTcpNotice->OnConnect(aoSocket, aoAddr);}void CEpollTcpSvr::OnCutdown(SOCKET aoSocket){if (m_pTcpNotice)m_pTcpNotice->OnClose(aoSocket);m_oConectMapLock.lock();std::unordered_map< SOCKET, S_TcpConnect* >::iterator  liIter = m_oConectMap.find(aoSocket);if (liIter != m_oConectMap.end()) {BackConnect(liIter->second);m_oConectMap.erase(aoSocket);}else {printf("INFO: UnKnowConnect");}m_iTotalCCnt = m_oConectMap.size();m_oConectMapLock.unlock();printf("[INFO] OnCutdown SOCKET:%d Total:%d\n", aoSocket, m_iTotalCCnt);epoll_ctl(m_oEpollFD, EPOLL_CTL_DEL, aoSocket, 0); // 为什么没有看到有人删除他closesocket(aoSocket);}void CEpollTcpSvr::UpdateEvents( EPOLL aoEpoll, SOCKET aoSocket, int aoEvent, int aoOpt ) {struct epoll_event loEvent;memset( &loEvent, 0, sizeof( loEvent ) );loEvent.events=aoEvent;loEvent.data.fd=aoSocket;epoll_ctl(aoEpoll, aoOpt, aoSocket, &loEvent);}bool CEpollTcpSvr::StartSvr(int aiPort, int aiTaskThreadCnt, int aiCatchSize, int aiMaxSocketCnt){if (m_bIsInit) return true;m_iMaxSocketCnt= aiMaxSocketCnt;m_iTaskThreadCnt= aiTaskThreadCnt;m_iMaxCacheSize= aiCatchSize;m_oLsnSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);CSocketHelper::SetNonBlock( m_oLsnSocket );CSocketHelper::SetReuseAddr(m_oLsnSocket);CSocketHelper::SetNodelay( m_oLsnSocket );struct sockaddr_in loAddr;memset(&loAddr, 0, m_iSockaddrinLen);loAddr.sin_family=AF_INET;loAddr.sin_port=htons(aiPort);loAddr.sin_addr.s_addr=INADDR_ANY;int ret = ::bind(m_oLsnSocket, (struct sockaddr*)&loAddr, m_iSockaddrinLen);if (SOCKET_ERROR == ret){closesocket(m_oLsnSocket);return false;}printf("[INFO] bind/n");ret = ::listen( m_oLsnSocket, 20 );if (SOCKET_ERROR == ret){closesocket(m_oLsnSocket);return false;}printf("[INFO] listen/n");m_oEpollFD = epoll_create(5);//UpdateEvents(m_oEpollFD, m_oLsnSocket, EPOLLIN , EPOLL_CTL_ADD);UpdateEvents(m_oEpollFD, m_oLsnSocket, EPOLLIN | EPOLLET| EPOLLERR, EPOLL_CTL_ADD);printf("[INFO] UpdateEvents/n");int err = pthread_create(&m_oWorkThread, NULL, _WorkThread, this); //创建线程  if (err != 0) {printf("[ERROR]create m_oWorkThread error: %s/n", strerror(err));return false;}err = pthread_create(&m_oCheckThread, NULL, _CheckThread, this); //创建线程  if (err != 0){printf("[ERROR]create m_oCheckThread error: %s/n", strerror(err));return false;}if (m_iTaskThreadCnt <= 0) m_iTaskThreadCnt = 1;m_pTaskThread = new pthread_t[m_iTaskThreadCnt];for ( int i = 0; i < m_iTaskThreadCnt; ++i ) {pthread_create(&m_pTaskThread[i], NULL, _TaskThread, this);}printf("[INFO] Start Succeed Epoll:%d Socket:%d LsnPort:%d\n", m_oEpollFD, m_oLsnSocket, aiPort);return true;}void* CEpollTcpSvr::_WorkThread(void * apThis) {printf("[INFO] _WorkThread\n");if (apThis){CEpollTcpSvr* lpThis = (CEpollTcpSvr*)apThis;lpThis->WorkThread();}return NULL;}void CEpollTcpSvr::WorkThread(void) {struct epoll_event loEvents[MAX_EVENT_NUM];while (true) {int liRet = epoll_wait(m_oEpollFD, loEvents, MAX_EVENT_NUM, -1); if (liRet == -1){if (errno == EINTR){printf("[INFO] Epoll wait EINTR Continue\n");continue;}else {printf("[INFO] Epoll wait Error\n");closesocket(m_oEpollFD);exit(EXIT_FAILURE);}}OnEpollET(loEvents, liRet, m_oEpollFD, m_oLsnSocket);}closesocket(m_oEpollFD);}bool CEpollTcpSvr::OnEpollET(struct epoll_event* aoEvents, int aiNum, EPOLL aoEpoll, SOCKET aoListenFd){char lszBuf[DEF_READ_BUF_TCP + 1];for (int i = 0; i < aiNum; ++i){int loClientFd = aoEvents[i].data.fd;if (loClientFd == aoListenFd){do{S_TcpConnect*lpConnect = GetConnect();socklen_t loAddrLen= m_iSockaddrinLen;lpConnect->m_oSocket = accept(aoListenFd, (struct sockaddr*)&lpConnect->m_oAddress, &loAddrLen);if (-1 == lpConnect->m_oSocket){if ( errno == EAGAIN){BackConnect(lpConnect);break;}else if (errno == EINTR){// 非阻塞状态应该不会出现的.printf("[INFO] Epoll accept EINTR\n");BackConnect(lpConnect);continue;}printf("[INFO] Epoll accept false\n");return false;}// 限制连接数if (m_iTotalCCnt > m_iMaxSocketCnt){closesocket(lpConnect->m_oSocket);BackConnect(lpConnect);break;}m_oConectMapLock.lock();m_oConectMap.insert(std::make_pair(lpConnect->m_oSocket, lpConnect));m_iTotalCCnt = m_oConectMap.size();m_oConectMapLock.unlock();CSocketHelper::SetNonBlock(lpConnect->m_oSocket);CSocketHelper::SetNodelay(lpConnect->m_oSocket);UpdateEvents(m_oEpollFD, lpConnect->m_oSocket, EPOLLIN|EPOLLET|EPOLLRDHUP|EPOLLERR, EPOLL_CTL_ADD);OnConnect(lpConnect->m_oSocket, lpConnect->m_oAddress);} while (true);}else {if (( aoEvents[i].events & EPOLLERR)  || ( aoEvents[i].events & EPOLLHUP)  || ( aoEvents[i].events & EPOLLRDHUP ) ){OnCutdown(aoEvents[i].data.fd);continue;}  do{S_TcpDataBuf*lpBuf = GetDataBuf();lpBuf->m_iBufLen = ::read(loClientFd, lpBuf->m_szBuf, DEF_READ_BUF_TCP);if ( lpBuf->m_iBufLen > 0 ){m_i64TotalRecvPackageCnt += 1;double ldTem = lpBuf->m_iBufLen;m_dTotalRecvKByte += ldTem / 1024;lpBuf->m_oSocket = loClientFd;m_oDataTaskBufQueueLock.lock();m_oDataTaskBufQueue.push(lpBuf);m_oDataTaskBufQueueLock.unlock();}else if ( lpBuf->m_iBufLen == -1 ){if ( ( errno == EAGAIN ) ){BackDataBuf(lpBuf);break;}else{BackDataBuf(lpBuf);OnCutdown(loClientFd);break;}}else{BackDataBuf(lpBuf);OnCutdown(loClientFd);break;}} while (true);}}return true;}void* CEpollTcpSvr::_CheckThread(void * apThis) {printf("[INFO] _CheckThread/n");if (apThis){CEpollTcpSvr* lpThis = (CEpollTcpSvr*)apThis;lpThis->CheckThread();}return NULL;}void CEpollTcpSvr::CheckThread(void) {int64_t li64OldRecvPackageCnt = 0;double ldwOldRecvKb = 0;int64_t li64OldSendPackageCnt = 0;double ldwOldSendKb = 0;while (true){int liSize1 = m_oDataCatchBufQueue.size();int liSize2 = m_oDataTaskBufQueue.size();printf("[INFO] CON:%d [R:(%ld %.2lf KB)(%ld %.2lfKB)][S:(%ld %.2lf KB)(%ld %.2lfKB)][BC:%d, BT:%d][CC:%d]\n",m_iTotalCCnt, m_i64TotalRecvPackageCnt,m_dTotalRecvKByte,(m_i64TotalRecvPackageCnt - li64OldRecvPackageCnt),(m_dTotalRecvKByte - ldwOldRecvKb),m_i64TotalSendPackageCnt, m_dTotalSendKByte,(m_i64TotalSendPackageCnt - li64OldSendPackageCnt),(m_dTotalSendKByte - ldwOldSendKb),m_oDataCatchBufQueue.size(), m_oDataTaskBufQueue.size(),m_oConnectCatchQueue.size());li64OldRecvPackageCnt = m_i64TotalRecvPackageCnt;ldwOldRecvKb = m_dTotalRecvKByte;li64OldSendPackageCnt = m_i64TotalSendPackageCnt;ldwOldSendKb = m_dTotalSendKByte;int a;a = 10;CrtSecSleep(1);}}void* CEpollTcpSvr::_TaskThread(void * apThis){if (apThis){CEpollTcpSvr* lpThis = (CEpollTcpSvr*)apThis;lpThis->TaskThread();}return NULL;}void CEpollTcpSvr::TaskThread(void){while (true){S_TcpDataBuf* lpBuf = NULL;{S_AutoLock lo(&m_oDataTaskBufQueueLock);if (m_oDataTaskBufQueue.size() > 0) {lpBuf = m_oDataTaskBufQueue.front();m_oDataTaskBufQueue.pop();}}if (lpBuf){if (m_pTcpNotice) {m_pTcpNotice->OnRecv(lpBuf->m_oSocket, lpBuf->m_szBuf, lpBuf->m_iBufLen);}//SendData(lpBuf->m_oSocket, lpBuf->m_szBuf, lpBuf->m_iBufLen);BackDataBuf(lpBuf);continue;}CrtMiscSleep(100);}}bool CEpollTcpSvr::SendData(SOCKET aoSocket, char* apBuf, int aiLen) {int liPerSend=0;int liNeedSend=aiLen;int liRealSend=0;while (true) {liPerSend = write(aoSocket, apBuf, liNeedSend);if ( liPerSend == -1 ){if ( errno == EAGAIN ){return true;}closesocket(aoSocket);return false;}else if (liPerSend == 0) {printf("[INFO] SOCKET CUTDOWN  %d\n", liPerSend);closesocket(aoSocket);return false;}liRealSend += liPerSend;if (liRealSend < aiLen){liNeedSend -= liPerSend;apBuf += liPerSend;}else if (liRealSend == aiLen)  break;}m_i64TotalSendPackageCnt++;double ldTemp = liRealSend;m_dTotalSendKByte += (ldTemp/1024);return true;}S_TcpDataBuf*CEpollTcpSvr::GetDataBuf(void){m_oDataCatchBufQueueLock.lock();if (m_oDataCatchBufQueue.size() > 0) {S_TcpDataBuf* lpBuf = m_oDataCatchBufQueue.front();m_oDataCatchBufQueue.pop();m_oDataCatchBufQueueLock.unlock();return lpBuf;}else {m_oDataCatchBufQueueLock.unlock();return  (new S_TcpDataBuf);}}void CEpollTcpSvr::BackDataBuf(S_TcpDataBuf* apBuf){m_oDataCatchBufQueueLock.lock();if (m_oDataCatchBufQueue.size() < m_iMaxCacheSize) {memset(apBuf, 0, sizeof(char)* DEF_READ_BUF_TCP);m_oDataCatchBufQueue.push(apBuf);m_oDataCatchBufQueueLock.unlock();}else {m_oDataCatchBufQueueLock.unlock();delete  apBuf;} }S_TcpConnect*CEpollTcpSvr::GetConnect(void) {m_oConnectCatchQueueLock.lock();if (m_oConnectCatchQueue.size() > 0){S_TcpConnect* lpConnect = m_oConnectCatchQueue.front();m_oConnectCatchQueue.pop();m_oConnectCatchQueueLock.unlock();return lpConnect;}else{m_oConnectCatchQueueLock.unlock();return  (new S_TcpConnect);}}void CEpollTcpSvr::BackConnect(S_TcpConnect* apConnect) {m_oConnectCatchQueueLock.lock();if (m_oConnectCatchQueue.size() < m_iMaxCacheSize){apConnect->m_oSocket = -1;memset(&apConnect->m_oAddress, 0, m_iSockaddrinLen);apConnect->m_i64ConnectTime = 0;m_oConnectCatchQueue.push(apConnect);m_oConnectCatchQueueLock.unlock();//printf("INFO:BACK %d\n", m_oConnectCatchQueue.size());}else{//printf("INFO:delete %d\n", m_oConnectCatchQueue.size());m_oConnectCatchQueueLock.unlock();delete  apConnect;}}