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

#ifndef		H_NETDEF_H
#define		H_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 EWOULDBLOCK				EAGAIN
	#define SOCKET_ERROR            (-1)
	#define closesocket				close
	#define INVALID_SOCKET			(SOCKET)(~0)
	typedef int SOCKET;
	typedef int EPOLL;
#endif

// TCP
#define DEF_READ_BUF_TCP	(1460)
struct S_TcpDataBuf
{
	char	m_szBuf[DEF_READ_BUF_TCP];
	int		m_iBufLen;
	SOCKET 	m_oSocket;
};

struct S_TcpConnect
{
	SOCKET					m_oSocket;
	struct sockaddr_in		m_oAddress;
	int64_t					m_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:Snight
QQ:51171107
*/

#ifndef H_DEF_EPOLLSVR_H
#define	H_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 );
	void		BackDataBuf(S_TcpDataBuf* apBuf );

	S_TcpConnect*	GetConnect(void);
	void		BackConnect(S_TcpConnect* apBuf);
private:
	bool											m_bIsInit;
	int												m_iSockaddrinLen;

	int												m_iMaxSocketCnt;
	SOCKET											m_oLsnSocket;
	EPOLL											m_oEpollFD;
	pthread_t										m_oWorkThread;
	
	pthread_t										m_oCheckThread;
	pthread_t*										m_pTaskThread;
	int												m_iTaskThreadCnt;

	ITcpNotice*										m_pTcpNotice;
	int												m_iTotalCCnt;
	
	int64_t											m_i64TotalRecvPackageCnt;
	double											m_dTotalRecvKByte;

	int64_t											m_i64TotalSendPackageCnt;
	double											m_dTotalSendKByte;

	// 缓存buf
	std::queue<S_TcpDataBuf*>						m_oDataCatchBufQueue;
	std::recursive_mutex							m_oDataCatchBufQueueLock;
	int												m_iMaxCacheSize;

	// 任务buf
	std::queue<S_TcpDataBuf*>						m_oDataTaskBufQueue;
	std::recursive_mutex							m_oDataTaskBufQueueLock;

	// 连接
	std::unordered_map< SOCKET, S_TcpConnect* >		m_oConectMap;
	std::recursive_mutex							m_oConectMapLock;

	// 缓存buf
	std::queue<S_TcpConnect*>						m_oConnectCatchQueue;
	std::recursive_mutex							m_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;
	}
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值