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


//IOCPNet.cpp 
#include "stdafx.h" 
#include "IOCPNet.h" 
 
/* 
	worker threads 
*/ 
CIOCPNet g_IOCPNet; 
::ofstream	g_closenumber; 
 
DWORD WINAPI _xThread(LPVOID pVoid) 
{ 
	CIOCPNet* pIOCPNet = (CIOCPNet*)pVoid; 
	pIOCPNet->Process(); 
	 
	return 1; 
} 
 
DWORD WINAPI _xListenThread(LPVOID pVoid)    
{ 
	CIOCPNet* pIOCPNet = (CIOCPNet*)pVoid; 
	pIOCPNet->Accept(); 
	return 1; 
} 
 
 
/* 
 
 
	CIOCPNet member functions 
 
*/ 
CIOCPNet::CIOCPNet()  
{ 
	int i = 0; 
	for (i = 0 ; i < IOCP_THREADS_PER_CPU ; i ++) m_hThreads[i] = NULL; 
	m_hIOCP = INVALID_HANDLE_VALUE; 
 
	for ( i = 0 ; i < SOCKET_MAX_LISTEN ; i++) m_ListenSoc[i] = INVALID_SOCKET; 
	InitializeCriticalSection(&m_ListenFlag); 
	InitializeCriticalSection(&m_ListenFlag_Server); 
	 
	for ( i = 0 ; i < IOCP_MAX_CLIENT_ACCPET ; i++) 
		g_ClientArray[i].SetClientNumber(i); 
 
	m_pMultiToken = NULL; 
	m_bPause = TRUE; 
	m_bOperate = TRUE; 
 
	m_dwCurrentTime = 0; 
	m_IOCPclosenumber.open( "IOCPclosenumber" ); 
	//set client 0 for multi server 
	m_iClients++; 
} 
 
CIOCPNet::~CIOCPNet() 
{ 
	m_IOCPclosenumber.close(); 
	DeleteCriticalSection(&m_ListenFlag); 
	DeleteCriticalSection(&m_ListenFlag_Server); 
} 
 
void CIOCPNet::GetLocalName(char* addr) 
{ 
	if (addr == NULL) return; 
	 
    char name[255]; 
	char* address; 
    PHOSTENT hostinfo; 
 
      if( gethostname ( name, sizeof(name)) == 0) 
            { 
                  if((hostinfo = gethostbyname(name)) != NULL) 
                  { 
                        address = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list); 
                  } 
				  else return; 
            } 
	  else return; 
    strcpy(addr,address); 
} 
bool CIOCPNet::Init(HWND hParents, CIOCPToken* pToken, CMultiToken* pMultiToken) 
{ 
	//¿©±â¼­ ¿­°í 
	g_closenumber.open("closenumber.txt"); 
 
	if (pToken == NULL) return false; 
 
	m_pToken	= pToken; 
	m_pMultiToken = pMultiToken; 
 
	//Get system info 
	GetSystemInfo(&m_SysInfo); 
 
	//create completion port ( cpu * IOCP_THREADS_PER_CPU ) ¾²·¡µå¼ö »ý¼º  
	if ((m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL,  0)) == NULL) 
		return false; 
 
	//create threads 
	HANDLE	hThread; 
	DWORD	dwThreadId; 
	for(DWORD dwi = 0; dwi m_nListenSocketCount + iPlus || i < m_pMultiToken->GetTotalServerCount(); i++) 
		{			 
			if( m_pMultiToken->m_SocInfo[i].bListen == false )  
			 iPlus++;				 
			else 
			 if (!InitListen(m_pMultiToken->m_SocInfo[i].nPort,(WORD)i,m_pMultiToken->m_SocInfo[i].szIP))	return FALSE; //listen fail 
		} 
		m_pMultiToken->Connect(this); 
	} 
	m_bPause = FALSE; 
 
	//Resume accept thread. 
	ResumeThread(m_hThreadAccept); 
	return true; 
} 
BOOL  CIOCPNet::InitListen(long port,WORD wlisten,char* LocalIP) 
{ 
	WSADATA 		wsaData; 
	SOCKADDR_IN 	serv_addr; 
 
	WORD wVer = MAKEWORD(2,0); 
	if(WSAStartup(wVer, &wsaData) != 0) return FALSE; 
 
	m_ListenSoc[wlisten] = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); 
 
 
	if ( m_ListenSoc[wlisten] == INVALID_SOCKET ) return FALSE; 
 
	if (LocalIP == NULL) 
	{ 
		serv_addr.sin_family = AF_INET; 
		serv_addr.sin_port = htons((unsigned short)port); 
		serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
	} 
	else 
	{ 
		serv_addr.sin_family = AF_INET; 
		serv_addr.sin_port = htons((unsigned short)port); 
		serv_addr.sin_addr.s_addr = inet_addr(LocalIP); 
	} 
 
 
	BOOL	bRe = TRUE; 
	setsockopt(m_ListenSoc[wlisten], SOL_SOCKET, SO_REUSEADDR, (char*) &bRe, sizeof(BOOL)); 
 
	if (bind (m_ListenSoc[wlisten], (LPSOCKADDR)&serv_addr, sizeof(serv_addr))== SOCKET_ERROR)  
	{ 
//		int k = WSAGetLastError(); 
		return FALSE; 
	} 
 
	BOOL opt = TRUE; 
	 
	if(SOCKET_ERROR == setsockopt(m_ListenSoc[wlisten], IPPROTO_TCP, TCP_NODELAY , (char*) &opt, sizeof(int))) 
		return FALSE; 
 
 
	LINGER			LingerStruct; 
	LingerStruct.l_onoff  = 1; 
	LingerStruct.l_linger = 0; 
 
	int nZero = 0; 
	opt = TRUE; 
	if(SOCKET_ERROR == setsockopt(m_ListenSoc[wlisten], SOL_SOCKET, SO_LINGER,(char*) &opt, sizeof(LingerStruct))) 
		return FALSE; 
 
 
	if (listen (m_ListenSoc[wlisten] , SOMAXCONN ) == SOCKET_ERROR)  
		return FALSE; 
 
 
	return TRUE; 
} 
 
 
 
/* 
	BOOL CIOCPNet::Accept() 
 
*/ 
BOOL CIOCPNet::Accept() 
{ 
	timeval TimeVal; 
	fd_set  Temp_set; 
 
	TimeVal.tv_sec  = 0; 
	TimeVal.tv_usec = 1; 
 
	if (m_pMultiToken == NULL) return 1; 
 
	while (m_bOperate) 
	{ 
		int iPlus = 0; 
		for (int i = 0 ; i < m_pMultiToken->m_nListenSocketCount + iPlus || i < m_pMultiToken->GetTotalServerCount() ; i++) 
		{ 
			if( m_pMultiToken->m_SocInfo[i].bListen == false )  
			 iPlus++;				 
			else 
			{ 
				if (m_ListenSoc[i] == INVALID_SOCKET) continue;				 
				 
				FD_ZERO (&Temp_set); 
				FD_SET (m_ListenSoc[i] , &Temp_set); 
				 
				select(IOCP_MAX_CLIENT_ACCPET, &Temp_set, NULL, NULL, &TimeVal); 
				 
				if (FD_ISSET (m_ListenSoc[i], &Temp_set)) 
				{ 
					Accept( m_ListenSoc[i],i,m_pMultiToken->m_SocInfo[i].nRecvSockBuffer, 
						m_pMultiToken->m_SocInfo[i].nSendSockBuffer, 
						m_pMultiToken->m_SocInfo[i].nReadQueueBuffer, 
						m_pMultiToken->m_SocInfo[i].nSendQueueBuffer); 
				} 
			} 
		} 
		Sleep(1); 
	} 
 
	return 1; 
} 
 
 
/* 
	BOOL CIOCPNet::Accept(SOCKET socket) 
 
*/ 
BOOL CIOCPNet::SockOptionSet(SOCKET soc,int nNum,int nRecvSockBuffer,int nSendSockBuffer) 
{ 
	//set options 
	if(SOCKET_ERROR == setsockopt(soc, SOL_SOCKET, SO_SNDBUF, (char*) &nSendSockBuffer, sizeof(nSendSockBuffer)))  
	{ 
		return FALSE; 
	} 
	if(SOCKET_ERROR == setsockopt(soc, SOL_SOCKET, SO_RCVBUF, (char*) &nRecvSockBuffer, sizeof(nRecvSockBuffer))) 
	{ 
		return FALSE; 
	} 
 
	int nZero = 0; 
	BOOL opt = TRUE; 
 
	//Nagle off 
	if(SOCKET_ERROR == setsockopt(soc, IPPROTO_TCP, TCP_NODELAY , (char*) &opt, sizeof(nZero))) 
		return FALSE;	 
 
	//linger option off 
 
	LINGER			LingerStruct; 
	LingerStruct.l_onoff  = 1; 
	LingerStruct.l_linger = 0; 
 
	nZero = 0; 
	opt = TRUE; 
	if(SOCKET_ERROR == setsockopt(soc, SOL_SOCKET, SO_LINGER,(char*) &opt, sizeof(LingerStruct))) 
		return FALSE; 
 
	return TRUE; 
 
} 
int CIOCPNet::GetEmptyClient() 
{ 
		DWORD	dwCooltime = GetTickCount(); 
		for (int i = BRAVO_MAX_MULTI_SERVER ; i < IOCP_MAX_CLIENT_ACCPET ; i ++) 
		{//find empty client! kkkk 
			if (!g_ClientArray[i].IsConnected() && (g_ClientArray[i].m_dwCoolTime < dwCooltime)) 
			{ 
				return i; 
			} 
		} 
		return -1; 
} 
BOOL CIOCPNet::Accept(SOCKET listen,int nNum,int nRecvSockBuffer,int nSendSockBuffer, 
					  int nReadQueueBuffer,int nSendQueueBuffer) 
{ 
 
	 
	 
	if(m_hIOCP == NULL) return FALSE; 
	//if (nNum != 0  && g_ClientArray[nNum].IsConnected()) // »ì¾Æ Àִµ¥? Áߺ¹ ¼­¹ö Á¢¼Ó?? 
	//{ 
	//	g_ClientArray[nNum].Close( 2000 ); 
	//} 
 
	SOCKADDR_IN	cli_addr; 
	int			cli_len; 
	cli_len = sizeof(cli_addr); 
 
	//accept socket 
	SOCKET socIncoming; 
	socIncoming = accept(listen, (LPSOCKADDR)&cli_addr, &cli_len); 
	 
	char ClientIP[25]; 
	memset(ClientIP,0x00,sizeof(char)*25); 
	 
	sprintf(ClientIP,"%d.%d.%d.%d",(int)(cli_addr.sin_addr.S_un.S_un_b.s_b1), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b2), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b3), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b4)); 
 
	if (nNum != 0  && g_ClientArray[nNum].IsConnected()) // »ì¾Æ Àִµ¥? Áߺ¹ ¼­¹ö Á¢¼Ó?? 
	{ 
		if( strcmp( m_pMultiToken->m_SocInfo[nNum].szLocalIP , ClientIP ) != 0 )//ÇöÀç ºÙÀ» ¼­¹ö¶û ºÙ°íÀÚ ÇÏ´Â ¼­¹ö°¡ ´Ù¸£¸é ¸®ÅÏ 
		{ 
			//MessageBox(NULL,m_pMultiToken->m_SocInfo[nNum].szLocalIP,"txt",MB_OK); 
			//MessageBox(NULL,ClientIP,"Clientip",MB_OK); 
			shutdown(socIncoming,SD_BOTH ); 
			closesocket(socIncoming); 
			return false; 
		} 
			//MessageBox(NULL,m_pMultiToken->m_SocInfo[nNum].szLocalIP,"txt",MB_OK); 
			//MessageBox(NULL,ClientIP,"Clientip",MB_OK); 
			shutdown(socIncoming,SD_BOTH ); 
			closesocket(socIncoming);		 
		g_ClientArray[nNum].Close( 2000 ); 
	} 
 
	if (socIncoming == INVALID_SOCKET) return FALSE; 
 
	if (!SockOptionSet(socIncoming,0,nRecvSockBuffer,nSendSockBuffer))  
	{ 
		shutdown(socIncoming,SD_BOTH ); 
		closesocket(socIncoming); 
		return FALSE; 
	} 
 
	 
	HANDLE hResult = NULL; 
 
	// Client ¹øÈ£¸¦ ¹Þ°í ..À̰ÍÀú°Í ¼¼ÆÃ. 
	if (nNum == 0 ) 
	{//client 
 
		EnterCriticalListen();	 
		int i = GetEmptyClient(); 
		if (i < 0){LeaveCriticalListen();closesocket(socIncoming);return FALSE;} 
		 
		g_ClientArray[i].Init(nReadQueueBuffer,nSendQueueBuffer); 
		g_ClientArray[i].SetSocket(socIncoming); 
		g_ClientArray[i].SetClientNumber(i); 
		g_ClientArray[i].SetConnectFlag(TRUE); 
		sprintf(g_ClientArray[i].m_szPeerName,"%d.%d.%d.%d",(int)(cli_addr.sin_addr.S_un.S_un_b.s_b1), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b2), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b3), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b4)); 
 
		m_iClients++; 
		hResult = CreateIoCompletionPort((HANDLE)g_ClientArray[i].GetSocket(), m_hIOCP, i, 0); 
		LeaveCriticalListen();  
		m_pToken->Connected(i); 
		g_ClientArray[i].Read(); 
	} 
	else 
	{//server 
		EnterCriticalSListen(); 
		g_ClientArray[nNum].Init(nReadQueueBuffer,nSendQueueBuffer); 
		g_ClientArray[nNum].SetSocket(socIncoming); 
		g_ClientArray[nNum].SetClientNumber(nNum); 
		g_ClientArray[nNum].SetConnectFlag(TRUE); 
		sprintf(g_ClientArray[nNum].m_szPeerName,"%d.%d.%d.%d",(int)(cli_addr.sin_addr.S_un.S_un_b.s_b1), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b2), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b3), 
															(int)(cli_addr.sin_addr.S_un.S_un_b.s_b4)); 
		m_iClients++; 
		hResult = CreateIoCompletionPort((HANDLE)g_ClientArray[nNum].GetSocket(), m_hIOCP, nNum, 0); 
		LeaveCriticalSListen(); 
		if (m_pMultiToken != NULL)	m_pMultiToken->Connected(nNum,nNum); // ´ÙÀ̾˷α׿¡ »óŸ¦ ¾Ë¸²  
		g_ClientArray[nNum].Read(); 
 
	} 
#ifdef IOCP_DEBUG 
	char connectstr[128]; 
	sprintf(connectstr,"%d client connected from %d listen socket \n",nNum,nNum); 
//*	OutputDebugString(connectstr); 
#endif	 
	 
	return TRUE; 
} 
void CIOCPNet::CloseClient(int iClient) 
{ 
	if (iClient < BRAVO_MAX_MULTI_SERVER) 
		EnterCriticalSListen(); 
	else 
		EnterCriticalListen(); 
 
 
	if (g_ClientArray[iClient].IsConnected() == TRUE)  
	{ 
		g_ClientArray[iClient].m_dwCoolTime = GetTickCount() + CLIENT_COOL_TIME; 
#ifdef IOCP_DEBUG 
		char closeinfo[128]; 
		sprintf(closeinfo,"%d client closed\n",iClient); 
//*		OutputDebugString(closeinfo); 
#endif 
		CancelIo((HANDLE)g_ClientArray[iClient].GetSocket()); 
		shutdown(g_ClientArray[iClient].GetSocket(),SD_RECEIVE); 
		closesocket(g_ClientArray[iClient].GetSocket()); 
		g_ClientArray[iClient].SetConnectFlag(FALSE); 
		if (iClient < BRAVO_MAX_MULTI_SERVER) //server 
		{ 
			if (m_pMultiToken != NULL) 
			{ 
				m_iClients--;		 
				g_ClientArray[iClient].m_dwLastReceviedCount = 0; 
				g_ClientArray[iClient].m_dwLastReceivedTime  = 0; 
				LeaveCriticalSListen();		 
				m_pMultiToken->DisConnect(iClient); 
				return;  
			} 
		} 
		else 
		{ 
			m_iClients--;		 
			g_ClientArray[iClient].m_dwLastReceviedCount = 0; 
			g_ClientArray[iClient].m_dwLastReceivedTime  = 0; 
			LeaveCriticalListen(); 
			m_pToken->DisConnected(iClient); 
			return; 
		} 
	} 
	else 
	{ 
#ifdef IOCP_DEBUG 
		char closeinfo[128]; 
		sprintf(closeinfo,"%d client closed second time\n",iClient); 
//*		OutputDebugString(closeinfo); 
#endif 
	} 
	if (iClient < BRAVO_MAX_MULTI_SERVER) 
		LeaveCriticalSListen(); 
	else 
		LeaveCriticalListen(); 
} 
/* 
	BOOL CIOCPNet::Process() 
	process read and write process 
	work in background 
*/ 
BOOL CIOCPNet::Process() 
{ 
	BOOL				bResult = FALSE; 
	DWORD				dwCompKey; 
	LPOVERLAPPED		lpOverlapped = NULL; 
	DWORD				dwTransferred = 0; 
	OVERLAPPED_BASE*	lpOverlappedBase = NULL; 
	int temcount = 0; 
	while(m_bOperate) 
	{ 
		bResult = GetQueuedCompletionStatus( 
												m_hIOCP, 
												&dwTransferred, 
												&dwCompKey, 
												&lpOverlapped, 
												INFINITE 
											); 
 
		if (bResult == 0) 
		{ 
			//clientÁ¾·áó¸® 
			m_IOCPclosenumber << "10" << "\n"; 
			CloseClient((int)dwCompKey); 
			continue; 
		} 
 
		lpOverlappedBase = (OVERLAPPED_BASE*)lpOverlapped; 
 
		if (dwTransferred == SOCKET_ERROR) 
		{//socket ¿¡·¯Àϰæ¿ì 
			if( GetLastError() != ERROR_IO_PENDING ) 
			{//error io pending ÀÌ ¾Æ´Ï¸é Ä¡¸íÀû ¿¡·¯ 
			    // linger ¿É¼Ç Ű°í ²÷´Â´Ù.. 
				m_IOCPclosenumber << "11" << "\n"; 
				CloseClient((int)lpOverlappedBase->m_iClient); 
			} 
			continue; 
		} 
		 
		//0¹ÙÀÌÆ® ¼º°øÀÏ °æ¿ì´Â ¼ÒÄÏÀÌ ²÷¾îÁø °æ¿ì 
		if (dwTransferred == 0) 
		{ 
			m_IOCPclosenumber << "12" << "\n"; 
			CloseClient((int)lpOverlappedBase->m_iClient); 
			continue; 
		} 
 
		switch (lpOverlappedBase->m_sEvent) 
		{ 
		case IOCP_EVENT_READ: 
			{ 
				//ÀоúÀ½ 
				//¸Þ¼¼Áö ºÐÇÒó¸® 
				AnalyizeMsg((int)lpOverlappedBase->m_iClient,dwTransferred); 
 
			} 
			break; 
		case IOCP_EVENT_WRITE: 
			{ 
				g_ClientArray[lpOverlappedBase->m_iClient].WriteFinish(dwTransferred); 
			} 
			break; 
		default :  
			m_IOCPclosenumber << "13" << "\n"; 
			CloseClient((int)dwCompKey); 
			break; 
		} 
	} 
 
	return TRUE; 
} 
DWORD CIOCPNet::GetMsgSize(_header Header,UINT iClient) 
{ 
	if (Header.wID[0] < IOCP_MAX_CLIENT_MESSAGES) 
	{ 
		if (Header.wID[1] >= BRAVO_ZONEMSG_KEY) //msg from zoneserver  
			return g_arydwMsgSize_fromClient[Header.wID[0]]; 
		else 
			return g_arydwMsgSize[Header.wID[0]]; 
	} 
	else 
	{ 
#ifdef IOCP_DEBUG 
		char log[128]; 
		sprintf(log,"%d client sent message is exceeded the header number(%d)\n",iClient,(int)Header.wID[0]); 
//*		OutputDebugString(log); 
#endif 
		return 0; 
	} 
	return 0; 
 
} 
/* 
 
  void CIOCPNet::AnalyizeMsg(UINT iClient,DWORD dwSize) 
 
  ¹ÞÀº ¹öÆÛÀÇ ³»¿ëÀ» ºÐ¼®ÇÏ¿© µµÂøÇÑ ¸Þ¼¼Áö´Â Readqueue ¿¡ ³Ö¾îÁØ´Ù 
 
*/ 
 
 
void CIOCPNet::AnalyizeMsg(UINT iClient,DWORD dwSize) 
{ 
//	g_ClientArray[iClient].EnterWriteCS(); 
 
	CXClient* pClient = (CXClient*)&(g_ClientArray[iClient]); 
 
	//even headers not arrived. return 
	pClient->m_XReceiveBuffer->m_dwSize += dwSize; 
	if (pClient->m_XReceiveBuffer->m_dwSize < sizeof(SIOCPPacket))  
	{	 
//		g_ClientArray[iClient].LeaveWriteCS(); 
		return; 
	} 
 
	DWORD	dwTempBufferPos = 0;			//used for multiful reeceived message 
 
	_header Header = *((_header*)(pClient->m_XReceiveBuffer->m_szBuffer)); 
	DWORD	MsgSize = 0; 
 
	// Çì´õ º¹È£È­ 
#ifdef CRYPT 
	if( iClient >= BRAVO_MAX_MULTI_SERVER ) 
	{ 
		g_Crypt.Decrypt( &Header, sizeof( _header ) ); 
	} 
#endif 
 
	MsgSize = GetMsgSize(Header, iClient); 
 
	if (MsgSize == 0) 	 
	{//undefined message 
 
//		g_ClientArray[iClient].LeaveWriteCS(); 
		pClient->Close(10000);return ; 
	} 
 
	////////////////////////////////////////////////////////////////////////// 
	// speed hack!!!! 
	m_IOCPclosenumber << "ÊÕµ½ " << iClient << " µÄ°ü " << Header.wID[0] << " ʱ¼ä " << g_dwCurTickTime << "\n"; 
	m_IOCPclosenumber.flush(); 
	////////////////////////////////////////////////////////////////////////// 
 
	int Rcount = 0; 
	while ( pClient->m_XReceiveBuffer->m_dwSize >= MsgSize )  
	{//defined message arrived 
 
			// º¹È£È­...¾Ïȣȭ°ü·Ã 6-20 
#ifdef CRYPT 
		if( iClient >= BRAVO_MAX_MULTI_SERVER ) 
		{ 
			g_Crypt.Decrypt( pClient->m_XReceiveBuffer->m_szBuffer + dwTempBufferPos, MsgSize ); 
		} 
#endif 
 
		if (!g_XReadQueue.InQueue(//message buffer 
							 pClient->m_XReceiveBuffer->m_szBuffer + dwTempBufferPos, 
							 MsgSize,					//this message size 
							 iClient,									//client number 
							 0, 
							 TRUE 
							 )) 
		{ 
			// in case of buffer overqueue errors 
//			g_ClientArray[iClient].LeaveWriteCS();					 
			pClient->Close(20000); 
			return; 
		} 
 
 
		//prepare for next message 
		dwTempBufferPos += MsgSize;						//current client buffer pos 
		pClient->m_XReceiveBuffer->m_dwSize -= MsgSize;	//current client buffer size 
 
		if (pClient->m_XReceiveBuffer->m_dwSize < sizeof(SIOCPPacket)) break; 
 
		_header Header = *((_header*)(pClient->m_XReceiveBuffer->m_szBuffer + dwTempBufferPos)); 
		 
#ifdef CRYPT 
		if( iClient >= BRAVO_MAX_MULTI_SERVER ) 
		{ 
			g_Crypt.Decrypt( &Header, sizeof( _header ) ); 
		} 
#endif 
 
		MsgSize = GetMsgSize(Header,iClient);							 
		if (MsgSize == 0) 	 
		{//undefined message 
//			g_ClientArray[iClient].LeaveWriteCS(); 
			pClient->Close(30000);return ; 
		}		 
		Rcount++; 
	}//end of while 
 
	//if unfinished data remains in client buffer 
	if (pClient->m_XReceiveBuffer->m_dwSize > 0) 
	{ 
		memcpy(pClient->m_XReceiveBuffer->m_szBuffer, 
			   pClient->m_XReceiveBuffer->m_szBuffer + dwTempBufferPos, 
			   pClient->m_XReceiveBuffer->m_dwSize); 
	} 
//	g_ClientArray[iClient].LeaveWriteCS(); 
	pClient->Read(); 
} 
 
 
void CIOCPNet::Stop() 
{ 
	m_bOperate = FALSE; 
 
	if (m_pMultiToken != NULL)	m_pMultiToken->Stop();	//Stop the Token 
 
	DWORD dwExitCode = 6; 
	TerminateThread(m_hThreadAccept,dwExitCode);	//Stop accept thread 
	if (m_pMultiToken != NULL)	m_pMultiToken->Stop();	//Stop the Token 
 
	 
	for (int i = 0 ; i < IOCP_THREADS_PER_CPU ; i++) 
	{ 
		dwExitCode = 10+i; 
		 TerminateThread( m_hThreads[i], dwExitCode);   // exit code for the thread 
	} 
	//¿©±â¼­ ´Ý°í 
	g_closenumber.close(); 
} 
/* 
 
	Connect(char* szPeerName, long port, int nClient) 
	óÀ½ÀÏ °æ¿ì¿¡´Â nClient == IOCP_MAX_CLIENT_ACCPET -1 
	Áß°£¿¡ ²÷¾îÁ³À»°æ¿ì¿¡´Â client ¹øÈ£¸¦ »õ·Î ¹ÞÁö¾Ê°í ±× ¹øÈ£·Î °Á 
*/ 
int CIOCPNet::Connect(char* szPeerName, long port, int nClient,char* szLocalIP,int SocReadBuffer,int SocWriteBuffer 
						,int ReadQueueBuffer,int SendQueueBuffer) 
{ 
	EnterCriticalSListen(); 
	UINT i; 
 
	SOCKADDR_IN sockaddr; 
	sockaddr.sin_port = htons((unsigned short)port); 
	DWORD  dwPeerAddress = inet_addr(szPeerName); 
 
	sockaddr.sin_addr.s_addr = inet_addr(szPeerName);//dwPeerAddress; 
	sockaddr.sin_family = AF_INET; 
 
 
	i = nClient; 
 
	SOCKET tempsocket= socket(AF_INET, SOCK_STREAM, 0); 
	if (tempsocket == INVALID_SOCKET)  
	{ 
		LeaveCriticalSListen(); 
		return  -1; 
	} 
 
	if (!SockOptionSet(tempsocket,0,SocReadBuffer,SocWriteBuffer)) return -1; 
 
	if (szLocalIP != NULL) 
	{ 
		SOCKADDR_IN local_addr;  
		local_addr.sin_family = AF_INET; 
		local_addr.sin_port = 0;	/// kernel chooses port 
		local_addr.sin_addr.s_addr = inet_addr( szLocalIP );		/// local address bind  
		if( bind( tempsocket, (struct sockaddr *)&local_addr, sizeof(local_addr) ) == SOCKET_ERROR )  
		{ 
			closesocket(tempsocket); 
			LeaveCriticalSListen(); 
			return -1; 
		} 
	} 
 
	if (0 != connect(tempsocket, (SOCKADDR *)&sockaddr, sizeof (SOCKADDR_IN))) 
	{ 
		closesocket(tempsocket); 
		LeaveCriticalSListen(); 
		return -1; 
	} 
 
	g_ClientArray[nClient].Init(ReadQueueBuffer,SendQueueBuffer);  // m_XReceiveBuffer.m_dwSize = 0;  m_Socket = INVALID_SOCKET;	·Î ¼ÂÆÃ  
	g_ClientArray[nClient].SetSocket(tempsocket);  //m_SocketÀ» ¼ÂÆÃÇÑ´Ù. 
	g_ClientArray[nClient].SetClientNumber(i); 
 
	HANDLE hResult = NULL; 
	hResult = CreateIoCompletionPort((HANDLE)g_ClientArray[nClient].GetSocket(), m_hIOCP, nClient, 0); 
 
	g_ClientArray[nClient].SetConnectFlag(TRUE); 
	LeaveCriticalSListen(); 
 
	if (!g_ClientArray[nClient].Read()) 
	{ 
 
		g_ClientArray[nClient].Close(50000); 
		return -1; 
	} 
#ifdef IOCP_DEBUG 
	char connectstr[128]; 
	sprintf(connectstr,"%d client successed to connect %s \n",i,szPeerName); 
//*	OutputDebugString(connectstr); 
#endif 
	return i;	 
}