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);
}