www.pudn.com > ChatRoom.zip > IOServerPackage.cpp, change:2011-08-02,size:8007b


#include "StdAfx.h" 
#include "IOServerPackage.h" 
 
CIOServerPackage::CIOServerPackage(CWnd* pParent) 
{ 
	m_pParent = pParent; 
 
	memset(m_aryEvents, 0, sizeof(m_aryEvents)); 
 
	memset(m_arySocketOlps, 0, sizeof(m_arySocketOlps)); 
 
	m_bInitWinSockFlag = FALSE; 
 
	m_socketListen = NULL; 
 
	m_hStopThreadEvent = NULL; 
 
	m_hThreadEndedEvent = NULL; 
 
	m_pThreadWorking = NULL; 
 
	m_nSocketNum = 0; 
 
	m_strErrorMsg = _T(""); 
} 
 
CIOServerPackage::~CIOServerPackage(void) 
{ 
	Close(); 
} 
 
void CIOServerPackage::Close() 
{ 
	if(m_pThreadWorking) 
	{ 
		SetEvent(m_hStopThreadEvent); 
		Sleep(10); 
		if(WaitForSingleObject(m_hThreadEndedEvent, 1000) != WAIT_OBJECT_0) 
		{ 
			TerminateThread(m_pThreadWorking->m_hThread, -1); 
			delete m_pThreadWorking; 
		} 
 
		m_pThreadWorking = NULL; 
	} 
 
	if(m_hStopThreadEvent) 
	{ 
		CloseHandle(m_hStopThreadEvent); 
		m_hStopThreadEvent = NULL; 
	} 
 
	if(m_hThreadEndedEvent) 
	{ 
		CloseHandle(m_hThreadEndedEvent); 
		m_hThreadEndedEvent = NULL; 
	} 
 
	if(m_socketListen) 
	{ 
		closesocket(m_socketListen); 
		m_socketListen = NULL; 
	} 
 
	for(int i=0; i<m_nSocketNum; i++) 
	{ 
		if(m_aryEvents[i]) 
		{ 
			WSACloseEvent(m_aryEvents[i]); 
			m_aryEvents[i] = NULL; 
		} 
 
		if(m_arySocketOlps[i].m_nIoType != TYPE_UNKNOW) 
		{ 
			m_arySocketOlps[i].m_olpClient.hEvent = NULL; 
			closesocket(m_arySocketOlps[i].m_socket); 
			m_arySocketOlps[i].m_socket = NULL; 
		} 
	} 
 
	if(m_bInitWinSockFlag) 
	{ 
		WSACleanup(); 
	} 
} 
 
void CIOServerPackage::FreeCSocketOlpItem(CSocketOverlap* pItem) 
{ 
	int nIndex = 0; 
	for(int i=0; i<m_nSocketNum; i++) 
	{ 
		if(m_arySocketOlps[i].m_socket == pItem->m_socket) 
		{ 
			nIndex = i; 
			break; 
		} 
	} 
 
	closesocket(m_arySocketOlps[nIndex].m_socket); 
	WSACloseEvent(m_arySocketOlps[nIndex].m_olpClient.hEvent); 
	if(nIndex < m_nSocketNum) 
	{ 
		for(int i=nIndex; i<m_nSocketNum;i++) 
		{ 
			m_arySocketOlps[i] = m_arySocketOlps[i+1]; 
			m_aryEvents[i] = m_aryEvents[i+1]; 
		} 
	} 
	m_nSocketNum --; 
} 
 
BOOL CIOServerPackage::InitWinSock() 
{ 
	if(!m_bInitWinSockFlag) 
	{ 
		WORD wRequestVersion; 
		WSADATA wsaData; 
		int nRet; 
 
		wRequestVersion = 2<<8 | 2; 
 
		nRet = WSAStartup(wRequestVersion, &wsaData); 
 
		if(nRet != 0) 
		{ 
			m_strErrorMsg = _T("加载库失败!"); 
			return FALSE; 
		} 
 
		if((wsaData.wVersion>>8) != 2 || (wsaData.wVersion &0xff) != 2) 
		{ 
			m_strErrorMsg = _T("库的版本不对!"); 
			WSACleanup(); 
			return FALSE; 
		} 
 
		m_bInitWinSockFlag = TRUE; 
	} 
 
	return TRUE; 
} 
BOOL CIOServerPackage::PostAccept() 
{ 
	DWORD dwTrans = 0; 
	DWORD dwRecvNum = 0; 
	CSocketOverlap  socketOlp; 
	m_arySocketOlps[m_nSocketNum] = socketOlp; 
	m_aryEvents[m_nSocketNum] = m_arySocketOlps[m_nSocketNum].m_olpClient.hEvent; 
 
	m_arySocketOlps[m_nSocketNum].m_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); 
	m_arySocketOlps[m_nSocketNum].m_nIoType = TYPE_ACCEPT; 
 
	BOOL bRet = AcceptEx(m_socketListen, m_arySocketOlps[m_nSocketNum].m_socket, m_arySocketOlps[m_nSocketNum].m_szBuf, NULL, 
		sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &dwTrans, &m_arySocketOlps[m_nSocketNum].m_olpClient); 
	if(!bRet) 
	{ 
		int nRet = GetLastError(); 
 
		if(GetLastError() != ERROR_IO_PENDING) 
		{ 
			return FALSE; 
		} 
	} 
	m_nSocketNum++; 
	if(m_nSocketNum > WSA_MAXIMUM_WAIT_EVENTS) 
	{ 
		m_nSocketNum = WSA_MAXIMUM_WAIT_EVENTS; 
	} 
 
	return TRUE; 
} 
 
BOOL CIOServerPackage::PostRecv(CSocketOverlap* pItem) 
{ 
	if(!pItem) 
	{ 
		return FALSE; 
	} 
 
	memset(pItem->m_szBuf, 0, sizeof(pItem->m_szBuf)); 
 
	WSABUF wsaBuf = {0}; 
	wsaBuf.buf = pItem->m_szBuf; 
	wsaBuf.len = MAX_BUF_SIZE; 
	DWORD dwTrans = 0; 
	DWORD dwFlag = 0; 
 
	pItem->m_nIoType = TYPE_READ; 
 
	int nRet = WSARecv(pItem->m_socket, &wsaBuf, 1, &dwTrans, &dwFlag, &pItem->m_olpClient, NULL); 
	//int a = GetLastError(); 
	if(nRet != 0) 
	{ 
		if(GetLastError() != ERROR_IO_PENDING) 
		{ 
			return FALSE; 
		} 
	} 
 
	return TRUE; 
} 
 
BOOL CIOServerPackage::SendData(char *pSendData, DWORD dwDataSize) 
{ 
	WSABUF wsaBuf; 
	DWORD dwRecvNum = 0,dwFlag = 0;		//必须赋初值 
	CSocketOverlap *pItem = NULL; 
 
	for(int i=0; i<m_nSocketNum; i++) 
	{ 
 
		if(m_arySocketOlps[i].m_socket) 
		{ 
			wsaBuf.buf = pSendData; 
			wsaBuf.len = dwDataSize; 
			dwRecvNum = 1024; 
			WSASend(m_arySocketOlps[i].m_socket, &wsaBuf, 1, &dwRecvNum, NULL, &m_arySocketOlps[i].m_olpClient, NULL); 
			//send(m_arySocketOlp[i].m_socket, (const char*)szBuf, dwDataLength, NULL); 
		} 
	} 
	return TRUE; 
} 
 
BOOL CIOServerPackage::SendMsg(CString strMsg) 
{ 
	BOOL bRet = FALSE; 
 
	if(m_pParent) 
	{ 
		bRet = m_pParent->SendMessage(UM_SHOW_MSG, (WPARAM)strMsg.GetBuffer(), (LPARAM)(strMsg.GetLength()+1)*sizeof(TCHAR)); 
	} 
	return bRet; 
} 
 
BOOL CIOServerPackage::StartServer(int nPortNum) 
{ 
	//如果不变灰的话,校验 
	if(!InitWinSock()) 
	{ 
		m_strErrorMsg = _T("库加载失败!不能启动服务器"); 
		return FALSE; 
	} 
 
	m_socketListen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); 
	if(INVALID_SOCKET == m_socketListen) 
	{ 
		m_strErrorMsg = _T("创建监听SOCKET失败!"); 
		Close(); 
		return FALSE; 
	} 
 
	sockaddr_in sockAddrServer; 
	sockAddrServer.sin_family = AF_INET; 
	sockAddrServer.sin_addr.s_addr = inet_addr("127.0.0.1"); 
	sockAddrServer.sin_port = htons(0x9527); 
 
	if(SOCKET_ERROR == bind(m_socketListen, (const SOCKADDR*)&sockAddrServer, sizeof(sockAddrServer))) 
	{ 
		m_strErrorMsg = _T("bind 失败!"); 
		Close(); 
		return FALSE; 
	} 
 
	if(SOCKET_ERROR == listen(m_socketListen, 5)) 
	{ 
		m_strErrorMsg = _T("监听失败!"); 
		Close(); 
		return FALSE; 
	} 
 
	if(!PostAccept()) 
	{ 
		m_strErrorMsg = _T("投递请求失败"); 
		Close(); 
		return FALSE; 
	} 
 
	SendMsg(_T("服务器启动成功!正在监听......")); 
 
	//启动线程 
	m_hStopThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
	m_hThreadEndedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
	if(INVALID_HANDLE_VALUE == m_hStopThreadEvent || 
		INVALID_HANDLE_VALUE == m_hThreadEndedEvent) 
	{ 
		m_strErrorMsg = _T("创建事件失败!"); 
		Close(); 
		return FALSE; 
	} 
 
	m_pThreadWorking = AfxBeginThread(ThreadWorking, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); 
	if(!m_pThreadWorking) 
	{ 
		m_strErrorMsg = _T("创建线程失败!"); 
		Close(); 
		return FALSE; 
	} 
	Sleep(10); 
	m_pThreadWorking->ResumeThread(); 
	return TRUE; 
} 
 
BOOL CIOServerPackage::StopServer() 
{ 
	Close(); 
	return TRUE; 
} 
 
 
UINT CIOServerPackage::ThreadWorking(LPVOID lpVoid) 
{ 
	CIOServerPackage* pThis = (CIOServerPackage*)lpVoid; 
 
	DWORD dwIndex = 0; 
	DWORD dwTrans = 0; 
	DWORD dwFlags = 0; 
	BOOL bRet; 
	CString strValue; 
 
	while(1) 
	{ 
		if(WaitForSingleObject(pThis->m_hStopThreadEvent, 1) == WAIT_OBJECT_0) 
		{ 
			break; 
		} 
		//TODO:1.WSAWaitForMultipleEvents 
		dwIndex = WSAWaitForMultipleEvents(pThis->m_nSocketNum, pThis->m_aryEvents, FALSE, 100, FALSE); 
		if(WAIT_TIMEOUT == dwIndex) 
		{ 
			continue; 
		} 
		dwIndex = dwIndex - WSA_WAIT_EVENT_0; 
		//TODO:2.重置事件:WSAResetEvent 
		WSAResetEvent(pThis->m_aryEvents[dwIndex]); 
 
		//TODO:3.WSAGetOverlappedResult(); 
		bRet = WSAGetOverlappedResult(pThis->m_arySocketOlps[dwIndex].m_socket, &pThis->m_arySocketOlps[dwIndex].m_olpClient,  
			&dwTrans, TRUE, &dwFlags); 
		if(!bRet) 
		{ 
			int nRet = GetLastError(); 
			continue; 
		} 
		switch(pThis->m_arySocketOlps[dwIndex].m_nIoType) 
		{ 
		case TYPE_ACCEPT: 
			pThis->PostAccept(); 
			pThis->PostRecv(&pThis->m_arySocketOlps[dwIndex]); 
			break; 
		case TYPE_READ: 
			if(dwTrans > 0) 
			{ 
				strValue.Format(_T("客户端:%s"), pThis->m_arySocketOlps[dwIndex].m_szBuf); 
				pThis->SendMsg(strValue); 
				pThis->PostRecv(&pThis->m_arySocketOlps[dwIndex]); 
			} 
			else 
			{ 
				strValue = _T("客户端已下线"); 
				pThis->SendMsg(strValue); 
				pThis->FreeCSocketOlpItem(&pThis->m_arySocketOlps[dwIndex]); 
			} 
 
			break; 
		} 
	} 
 
	SetEvent(pThis->m_hThreadEndedEvent); 
 
	return 1; 
}