www.pudn.com > back.rar > iocpclient.cpp


//xclient.cpp 
#include "stdafx.h" 
#include "IOCPNet.h" 
 
//extern declaration 
CXReadQueue g_XReadQueue; 
 
 
//Àӽà ¼±¾ð 
CXClient g_ClientArray[IOCP_MAX_CLIENT_ACCPET]; 
/************************************************************************************** 
 
	CXReadQueue member functions 
 
*/ 
/* 
 
	const & dist 
 
*/ 
CXReadQueue::CXReadQueue() 
{ 
 
	enter = 0; 
	m_dwCurrentReadAds	= 0; 
	m_dwCurrentWriteAds	= 0; 
	m_dwCurrentMsgCnt	= 0; 
	m_dwQueueSize		= 0; 
	m_dwInitQueueSize	= MAX_READ_QUEUE_SIZE; 
	m_dwQueueCCrUsing	= MAX_READ_QUEUE_SIZE;//ends pointer 
	m_pReadBuffer		= new BYTE[MAX_READ_QUEUE_SIZE]; 
//	InitializeCriticalSectionAndSpinCount(&m_csFlag,2000); 
	InitializeCriticalSection(&m_csFlag); 
 
	m_log.open("readqueue_over.txt"); 
} 
CXReadQueue::~CXReadQueue() 
{ 
	DeleteCriticalSection(&m_csFlag); 
	delete  [] m_pReadBuffer; 
} 
 
/* 
 
  BOOL CXReadQueue::InQueue (BYTE* szBuffer,DWORD dwSize,UINT iClient) 
  Put a defined message into the ReadQueue 
 
*/ 
int tempcount = 0; 
DWORD temptimes = 0; 
DWORD ReadCount = 0; 
DWORD usedcount = 0; 
BOOL CXReadQueue::InQueue (BYTE* szBuffer,DWORD dwSize,UINT iClient,DWORD CurrentTime,BOOL bSeq) 
{ 
 
	EnterCritical(iClient); 
	 
	#ifdef IOCP_DEBUG	//debug 
	tempcount +=(int)dwSize; 
	ReadCount++; 
	DWORD curtimes = GetTickCount(); 
	if (temptimes + 1000 < curtimes) 
	{ 
		temptimes = curtimes; 
		char log[128]; 
		sprintf(log,"%d bytes read / sec (%d average queuesize , %d ReadCount / sec , %d turned) \n",(int)tempcount, 
			(int)(tempcount/ReadCount),ReadCount,usedcount); 
		m_log << (int)tempcount << "bytes read / sec, " << (int)(tempcount/ReadCount) << "average queuesize, " 
			<< ReadCount << "ReadCount / sec, " << usedcount << "turned" << "\n"; 
//*		OutputDebugString(log); 
		tempcount = 0; 
		ReadCount = 0; 
	} 
	#endif 
 
#ifdef IOCP_MSG_SEQ 
	if (bSeq == TRUE && ((SIOCPPacket*)szBuffer)->m_dwSeq != g_ClientArray[iClient].m_iRecvSeq++) 
	{ 
		#ifdef IOCP_DEBUG 
		char log[128]; 
		sprintf(log,"(!) client(%d) recv sequence is not identical (%d, %d)\n",iClient,(int)((SIOCPPacket*)szBuffer)->m_dwSeq,(int)g_ClientArray[iClient].m_iRecvSeq-1); 
		m_log << "(!) client(" << iClient << ") recv sequence is not identical (" << (int)((SIOCPPacket*)szBuffer)->m_dwSeq << ", " 
			<< (int)g_ClientArray[iClient].m_iRecvSeq-1 << ")" << "\n"; 
//*		OutputDebugString(log); 
		#endif 
		LeaveCritical(); 
		g_ClientArray[iClient].Close(0); 
		return FALSE; 
	} 
#endif  
 
	if ((dwSize + sizeof(SReadQueueBuffer_Header) + m_dwQueueSize) >  
		(m_dwInitQueueSize - IOCP_MAX_SIZE_PER_MESSAGES)) 
	{//read queue over 
		#ifdef IOCP_DEBUG 
		char log[128]; 
		sprintf(log,"(!) read queue over total(%d), Curr(%d), Add(%d) , Msgs(%d) , Using(%d) \n",(int)m_dwInitQueueSize,(int)m_dwQueueSize,(int)(dwSize + sizeof(SReadQueueBuffer_Header)),(int)m_dwCurrentMsgCnt,(int)m_dwQueueCCrUsing); 
		m_log << "(!) read queue over total(" << (int)m_dwInitQueueSize << "), Curr(" << (int)m_dwQueueSize << "), Add(" << (int)(dwSize + sizeof(SReadQueueBuffer_Header)) 
			<< ") , Msgs(" << (int)m_dwCurrentMsgCnt << ") , Using(" << (int)m_dwQueueCCrUsing << ")" << "\n"; 
//*		OutputDebugString(log); 
		#endif 
		LeaveCritical(); 
		return FALSE; 
	} 
 
	if (m_dwInitQueueSize - m_dwCurrentWriteAds < IOCP_MAX_SIZE_PER_MESSAGES) 
	{//in case of queue pointer reach the ends, reset pointer to zero 
		m_dwQueueCCrUsing = m_dwCurrentWriteAds; 
		m_dwCurrentWriteAds = 0; 
		usedcount++; 
	} 
	 
	//input header 
	SReadQueueBuffer_Header* pHeader = (SReadQueueBuffer_Header*)&m_pReadBuffer[m_dwCurrentWriteAds]; 
	pHeader->m_dwSize  = dwSize; 
	pHeader->m_iClient = iClient; 
	m_dwCurrentWriteAds += sizeof(SReadQueueBuffer_Header);  
	m_dwQueueSize += sizeof(SReadQueueBuffer_Header);  
	//input body 
 
	memcpy(m_pReadBuffer + m_dwCurrentWriteAds,szBuffer,dwSize); 
	m_dwCurrentWriteAds += dwSize; 
	m_dwQueueSize += dwSize; 
 
	m_dwCurrentMsgCnt++; 
	LeaveCritical(); 
	return TRUE; 
} 
SReadQueueBuffer_Header* CXReadQueue::OutQueue(BYTE** pBuffer) 
{ 
	EnterCritical(0); 
 
	if ((int)m_dwCurrentReadAds < 0 || (int)m_dwCurrentWriteAds < 0 || (int)m_dwCurrentMsgCnt < 0 || (int)m_dwQueueSize < 0 ||  
		(int)m_dwInitQueueSize < 0 || (int)m_dwQueueCCrUsing < 0) 
	{//critical err 
		#ifdef IOCP_DEBUG 
		char log[128]; 
		sprintf(log,"read queue data or info have critical error! (%d,%d,%d,%d,%d,%d)", 
			(int)m_dwCurrentReadAds ,(int) m_dwCurrentWriteAds ,(int) m_dwCurrentMsgCnt ,(int) m_dwQueueSize , 
			(int)m_dwInitQueueSize ,(int) m_dwQueueCCrUsing); 
		m_log << "read queue data or info have critical error!" << (int)m_dwCurrentReadAds << ", " << (int)m_dwCurrentWriteAds 
			  << ", " << (int)m_dwCurrentMsgCnt << ", " << (int)m_dwQueueSize << ", " << (int)m_dwInitQueueSize << ", " 
			  << (int)m_dwQueueCCrUsing << "\n"; 
//*		OutputDebugString(log); 
 
		#endif 
		LeaveCritical(); 
		return NULL; 
	} 
 
	if (m_dwQueueSize <= 0) {LeaveCritical(); return NULL; }	//no msg in queue 
 
 
	if (m_dwInitQueueSize - m_dwCurrentReadAds < IOCP_MAX_SIZE_PER_MESSAGES) 
	{ 
		m_dwCurrentReadAds = 0; 
		m_dwQueueCCrUsing = m_dwInitQueueSize; 
	} 
 
	//get header 
	SReadQueueBuffer_Header* pHeader = (SReadQueueBuffer_Header*)(m_pReadBuffer + m_dwCurrentReadAds); 
	m_dwCurrentReadAds += sizeof(SReadQueueBuffer_Header); 
	m_dwQueueSize -= sizeof(SReadQueueBuffer_Header); 
 
	//get body 
	*pBuffer = (BYTE*)(m_pReadBuffer + m_dwCurrentReadAds); 
	m_dwCurrentReadAds += pHeader->m_dwSize; 
	m_dwQueueSize -= pHeader->m_dwSize; 
 
	m_dwCurrentMsgCnt--; 
 
	LeaveCritical(); 
 
	return pHeader; 
} 
 
/************************************************************************************** 
 
	CXClient member functions 
 
*/ 
//base construction------------------------------ 
CXClient::CXClient() 
{ 
	m_Socket			= INVALID_SOCKET; 
	m_bCencelIO			= FALSE; 
	m_dwLastReceivedTime = 0; 
	m_XReceiveBuffer = NULL; 
	m_XSendBuffer	 = NULL; 
	m_dwInitCnt		 = 0; 
	m_dwCoolTime     = 0; 
 
	InitializeCriticalSection(&m_csSWriteflag); 
} 
CXClient::~CXClient() 
{ 
	m_Socket = INVALID_SOCKET; 
	DeleteCriticalSection(&m_csSWriteflag); 
} 
bool CXClient::Init(int buffersize,int WritebufferSize) 
{ 
	if (m_XReceiveBuffer == NULL) 
		m_XReceiveBuffer = new SXClientBuffer; 
 
	m_XReceiveBuffer->m_dwTotalBufferSize = buffersize; 
	if (m_XReceiveBuffer->m_szBuffer == NULL) 
		m_XReceiveBuffer->CreateBuffer(buffersize); 
	m_XReceiveBuffer->m_dwSize = 0; 
 
	if (m_XSendBuffer == NULL) 
		m_XSendBuffer = new SXClientBuffer; 
 
	m_XSendBuffer->m_dwTotalBufferSize = WritebufferSize; 
	if (m_XSendBuffer->m_szBuffer == NULL) 
		m_XSendBuffer->CreateBuffer(WritebufferSize); 
	m_XSendBuffer->m_dwSize = 0; 
	m_XSendBuffer->m_dwSize_Sent = 0; 
	m_XSendBuffer->m_bIOPending = FALSE; 
 
	m_iRecvSeq = 0; 
	m_iSendSeq = 0;  
 
	m_Socket = INVALID_SOCKET;	 
 
	m_dwLastReceviedCount = 0; 
	m_dwLastReceivedTime  = 0; 
 
	m_dwInitCnt++; 
	return true; 
} 
 
 
/* 
 
	Set Read operation in queue 
 
*/ 
BOOL CXClient::Read(WORD wSize) 
{ 
	//get valid buffer pos 
	if (!m_bConnected)  
	{ 
		return FALSE; 
	} 
 
	BYTE* pbyPos = m_XReceiveBuffer->m_szBuffer + m_XReceiveBuffer->m_dwSize; 
 
	m_XReceiveBuffer->m_Overlapped.m_sEvent  = IOCP_EVENT_READ; 
	m_XReceiveBuffer->m_Overlapped.m_iClient = m_iClient; 
	m_XReceiveBuffer->m_Overlapped.Internal	= m_XReceiveBuffer->m_Overlapped.InternalHigh 
											= m_XReceiveBuffer->m_Overlapped.Offset  
											= m_XReceiveBuffer->m_Overlapped.OffsetHigh  
											= 0;  
 
	 
 
	if (!ReadFile ((HANDLE)m_Socket,pbyPos,m_XReceiveBuffer->m_dwTotalBufferSize-m_XReceiveBuffer->m_dwSize, 
					NULL,&(m_XReceiveBuffer->m_Overlapped))) 
	{ 
		int err = GetLastError(); 
			 
		if (err != ERROR_IO_PENDING) 
		{ 
			int i = GetLastError(); 
			Close(1); 
			return FALSE; 
		} 
	} 
	return TRUE; 
} 
/* 
 
	Set Write  operation in queue 
 
*/ 
//bool CXClient::Write(BYTE* szBuffer,DWORD dwSize) 
 
#ifdef IOCP_DEBUG 
DWORD temptime = 0; 
DWORD PENDINGCOUNT = 0; 
DWORD SENTCOUNT = 1; 
DWORD EVERSENT = 0; 
DWORD sent = 0; 
DWORD sentall = 0; 
#endif 
int CXClient::Write(BYTE* szBuffer,DWORD dwSize,BOOL bExtra) 
{ 
	 
	if (!m_bConnected) return -1;//socket not connected  
	if (dwSize == 0)   return 3;   //no size ? 
 
	sent += dwSize; 
 
	EnterWriteCS(); 
	if (m_XSendBuffer->m_dwSize + dwSize > m_XSendBuffer->m_dwTotalBufferSize) 
	{//size overflow, slow client cut 
		#ifdef IOCP_DEBUG 
		char str[128]; 
		sprintf(str,"%d client writequeue(%d) over, disconnect!  \n",m_iClient,m_XSendBuffer->m_dwSize + dwSize); 
//*		OutputDebugString(str); 
		#endif 
		LeaveWriteCS(); 
		Close(2); 
		return -2; 
	} 
 
#ifdef IOCP_MSG_SEQ 
	((SIOCPPacket*)szBuffer)->m_dwSeq = m_iSendSeq++; 
#endif  
 
	if (!bExtra) 
	{//Extra information is not used 
		if (((SIOCPPacket*)szBuffer)->m_Header.wID[0] == 25) 
		{ 
			int i = 0 ; 
		} 
 
		((SIOCPPacket*)szBuffer)->m_Header.wID[1] = 0; 
	} 
 
	memcpy(m_XSendBuffer->m_szBuffer+m_XSendBuffer->m_dwSize,szBuffer,dwSize); 
	m_XSendBuffer->m_dwSize += dwSize; 
 
	if (m_XSendBuffer->m_bIOPending == FALSE)  
	{ 
		WriteSocket();//IOCP 
		return 1;  
	} 
	LeaveWriteCS(); 
 
	return 2; //pending 
} 
 
void  CXClient::WriteSocket() 
{ 
	//overlapped ÀÇ id °É¾îÁÖ°í (³ªÁß¿¡ write queue °ü¸®¸¦ À§ÇØ) 
 
	m_XSendBuffer->m_dwSize_Sent = m_XSendBuffer->m_dwSize; 
	m_XSendBuffer->m_Overlapped.m_iWritten = 0; 
	m_XSendBuffer->m_Overlapped.m_sEvent	= IOCP_EVENT_WRITE; 
	m_XSendBuffer->m_Overlapped.m_iClient	= m_iClient; 
	m_XSendBuffer->m_Overlapped.Internal	= m_XSendBuffer->m_Overlapped.InternalHigh 
											= m_XSendBuffer->m_Overlapped.Offset  
											= m_XSendBuffer->m_Overlapped.OffsetHigh = 0;  
 
#ifdef CRYPT	//¾Ïȣȭ 
		if( m_iClient >= BRAVO_MAX_MULTI_SERVER ) 
			g_Crypt.Encrypt( (void*)(m_XSendBuffer->m_szBuffer),  
									m_XSendBuffer->m_dwSize ); 
#endif 
	 
	#ifdef IOCP_DEBUG 
	if (temptime + 1000 < GetTickCount()) 
	{ 
		char temps[256]; 
		sprintf(temps,"(client %d) queuesize : %d , Sent : %d  Pending : %d ,TotalSent : %d ,Ever : %d\n",(int)m_iClient,sent,sentall,PENDINGCOUNT,SENTCOUNT,(int)EVERSENT/SENTCOUNT); 
//*		OutputDebugString(temps); 
		temptime = GetTickCount(); 
		sent = 0; 
		PENDINGCOUNT = 0; 
		SENTCOUNT = 1; 
		EVERSENT = 0; 
		sentall =0; 
	} 
	#endif 
	 
	DWORD result; 
	if ( !	WriteFile((HANDLE)m_Socket,				//handle 
					m_XSendBuffer->m_szBuffer,		//data 
					m_XSendBuffer->m_dwSize_Sent,	//size 
					NULL,							//ignore 
					&(m_XSendBuffer->m_Overlapped)))//overlapped 
		{			 
			result	=	WSAGetLastError(); 
			if (result != ERROR_IO_PENDING) 
			{//IO PENDING 
				LeaveWriteCS(); 
				Close(3); 
				return; 
			} 
			#ifdef IOCP_DEBUG 
			else  
			{ 
				PENDINGCOUNT++; 
				SENTCOUNT ++; 
				EVERSENT +=m_XSendBuffer->m_dwSize_Sent;				 
			} 
			#endif 
		} 
 
	#ifdef IOCP_DEBUG 
	else 
	{ 
		EVERSENT  +=m_XSendBuffer->m_dwSize_Sent; 
		SENTCOUNT ++; 
	} 
	#endif 
 
	m_XSendBuffer->m_bIOPending = TRUE; 
	LeaveWriteCS(); 
} 
void CXClient::WriteFinish(int sented) 
{ 
	EnterWriteCS(); 
	m_XSendBuffer->m_bIOPending = FALSE; 
 
	#ifdef IOCP_DEBUG 
	sentall += sented; 
	if (sented != (int)m_XSendBuffer->m_dwSize_Sent) 
	{ 
		char temps[256]; 
		sprintf(temps,"(client %d) buffer sent(%d) and real sent(%d) diffrent \n",(int)m_iClient,m_XSendBuffer->m_dwSize_Sent,sented); 
//*		OutputDebugString(temps); 
	} 
	#endif 
 
	if (sented < (int)m_XSendBuffer->m_dwSize) 
	{//º¸³»°í ÀÖ´ø»çÀÌ ¸Þ¼¼Áö°¡ ÂÍ ½×¿´±º ¶¯ÄÑÁÖÀð 
		memcpy(m_XSendBuffer->m_szBuffer  
			  ,m_XSendBuffer->m_szBuffer+m_XSendBuffer->m_dwSize_Sent, 
			   m_XSendBuffer->m_dwSize-m_XSendBuffer->m_dwSize_Sent); 
 
		m_XSendBuffer->m_dwSize -= m_XSendBuffer->m_dwSize_Sent; 
		m_XSendBuffer->m_dwSize_Sent = 0; 
 
		WriteSocket(); 
		return; 
 
	} 
	else 
	{//buffer reset 
		m_XSendBuffer->m_dwSize = 0; 
		m_XSendBuffer->m_dwSize_Sent = 0; 
	} 
	LeaveWriteCS(); 
} 
void CXClient::Close(int closenumber) 
{ 
#ifndef CLOSE_LOG 
	g_closenumber << closenumber << "\n";	 
#endif 
	g_IOCPNet.CloseClient(m_iClient); 
}