www.pudn.com > IOCPTest.rar > SocketClass.cpp


// SocketClass.cpp: implementation of the CSocketClass class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "SocketClass.h" 
#include  
 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CSocketClass::CSocketClass() 
{ 
	m_bConnect = FALSE; 
	m_bInProgress = FALSE; 
 
	m_hSocket = NULL; 
	m_hEvent = NULL; 
	m_hThread = NULL; 
	InitializeCriticalSection(&m_criticalSection); 
	m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
 
	m_nCnt = 0; 
} 
 
CSocketClass::~CSocketClass() 
{ 
    Stop(); 
	closesocket(m_hSocket);	 
	WSACloseEvent(m_hEvent); 
	CloseHandle(m_hThread); 
	DeleteCriticalSection(&m_criticalSection); 
    CloseHandle(m_hKillEvent); 
} 
 
 
bool CSocketClass::Init(const CString& strIPAddr, int nPort, HWND hWnd) 
{ 
 
	m_nPort = nPort; 
	m_strIPAddr = strIPAddr; 
 
	m_hWnd = hWnd; 
 
	 
	m_hThread= 
			(HANDLE)_beginthreadex(NULL,									// Security 
				 0,											// Stack size - use default 
				 SocketThreadProc,     			// Thread fn entry point 
				 (void*) this,	       
				 0,											// Init flag 
				 &m_dwThreadId);					// Thread address 
	 
 
 
	return TRUE; 
} 
 
void CSocketClass::Stop() 
{ 
    ::SetEvent(m_hKillEvent); 
    WaitForSingleObject(m_hThread, INFINITE); 
} 
 
unsigned CSocketClass::SocketThreadProc(LPVOID lParam) 
{ 
 
	CSocketClass* pThis = reinterpret_cast(lParam); 
 
 
	WSANETWORKEVENTS events; 
 
	bool bExit = false; 
	while(!bExit) 
	{ 
		// 
		// Wait for something to happen 
		// 
        if (WaitForSingleObject(pThis->m_hKillEvent, 100) == WAIT_OBJECT_0) 
            break; 
 
 
			if (!pThis->Connect()) 
		{ 
			Sleep(1000); 
			continue; 
		} 
 
		DWORD dwRet; 
		dwRet = WSAWaitForMultipleEvents(1, 
									 &pThis->m_hEvent, 
									 FALSE, 
									 100, 
									 FALSE); 
 
		if (dwRet == WSA_WAIT_TIMEOUT) 
			continue; 
 
		// 
		// Figure out what happened 
		// 
		int nRet = WSAEnumNetworkEvents(pThis->m_hSocket, 
								 pThis->m_hEvent, 
								 &events); 
		 
		if (nRet == SOCKET_ERROR) 
		{ 
			CString str; 
			str.Format("WSAEnumNetworkEvents error %ld\n",WSAGetLastError()); 
			::PostMessage(pThis->m_hWnd, WM_STATUS_MSG, 0,(LPARAM) AllocBuffer(str)); 
 
			break; 
		} 
 
		//				 // 
		// Handle events // 
		//				 // 
 
		// ACCEPT 
		bExit = pThis->ProcessNetworkMessage(events.lNetworkEvents); 
 
	} // while.... 
 
	return 0; // Normal Thread Exit Code... 
} 
 
bool CSocketClass::OnRead() 
{ 
 
 
	DWORD dwSize = 0; 
	int nRet = ioctlsocket(m_hSocket, FIONREAD, &dwSize); 
 
	if (nRet == -1) 
		return true; 
 
	if (dwSize == 0) 
		return false; 
 
 
	BYTE* pData = new BYTE[dwSize+1]; 
	 
	int nRead = recv(m_hSocket, (char*) pData, dwSize, 0); 
	if (nRead == -1) 
		return true; 
 
 
	m_recvBuff.Write(pData, nRead); 
	delete [] pData; 
 
	while (m_recvBuff.GetBufferLen() > (sizeof(int)*1)) 
	{ 
		int nSize = 0; 
		int nCommand = 0; 
		int nPageId = 0; 
		CopyMemory(&nSize, m_recvBuff.GetBuffer(), sizeof(int)); 
		 
 
		if (nSize && m_recvBuff.GetBufferLen() >= nSize) 
		{ 
			// Read off header 
			m_recvBuff.Read((PBYTE) &nSize, sizeof(int)); 
 
		//////////////////////////////////////////////////////// 
			//////////////////////////////////////////////////////// 
			// SO you would process your data here 
			//  
			// I'm just going to post message so we can see the data 
			nSize -= sizeof(int); 
 
			int nTrueSize = nSize+1; 
			PBYTE pData = new BYTE[nTrueSize]; 
			 
			CString str; 
 
			m_recvBuff.Read(pData,nSize); 
			pData[nTrueSize-1] =  NULL; 
			str = pData; 
			::PostMessage(m_hWnd, WM_REC_MSG, 0, (LPARAM) AllocBuffer(str)); 
			m_bReadHeader = TRUE; 
 
			// Clean Up 
			delete [] pData; 
		} 
		else 
			break; 
	} 
 
	return false; 
 
} 
 
bool CSocketClass::OnWrite() 
{ 
	return false; 
} 
bool CSocketClass::OnClose() 
{ 
	m_bConnect = FALSE; 
	::PostMessage(m_hWnd, WM_STATUS_MSG, 0, (LPARAM) AllocBuffer("Client Disconnected")); 
	return false; 
} 
bool CSocketClass::OnConnect() 
{ 
	m_bConnect = TRUE; 
	m_bInProgress = FALSE; 
	::PostMessage(m_hWnd, WM_STATUS_MSG, 0, (LPARAM) AllocBuffer("Client Connected")); 
	return false; 
} 
 
BOOL CSocketClass::Connect() 
{ 
	if  (m_bConnect || m_bInProgress) 
		return TRUE; 
 
	m_bReadHeader = TRUE; 
 
	if (m_hEvent) 
	{ 
		WSACloseEvent(m_hEvent); 
		m_hEvent = NULL; 
	} 
	if (m_hSocket) 
	{ 
		closesocket(m_hSocket); 
		m_hSocket = NULL; 
	} 
	 
 
	m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
 
	if (m_hSocket == INVALID_SOCKET) 
	{ 
		TRACE("Could not create  socket %ld\n",WSAGetLastError()); 
		return FALSE; 
	} 
 
 
	SOCKADDR_IN		saServer;		 
 
	memset(&saServer,0,sizeof(saServer)); 
 
	saServer.sin_family = AF_INET; 
	saServer.sin_addr.s_addr = inet_addr(m_strIPAddr); 
	saServer.sin_port = htons(m_nPort); 
	int nRet = connect(m_hSocket,(sockaddr*)&saServer, sizeof(saServer)); 
 
	if (nRet == SOCKET_ERROR && 
		WSAGetLastError() != WSAEWOULDBLOCK) 
	{ 
		TRACE("connect() error %ld\n",WSAGetLastError()); 
 
		closesocket(m_hSocket); 
 
		return FALSE; 
	} 
	 
	 
	m_bInProgress = TRUE; 
 
	m_hEvent = WSACreateEvent(); 
	if (m_hEvent == WSA_INVALID_EVENT) 
	{ 
		closesocket(m_hSocket); 
		return FALSE; 
	} 
 
	// 
	// Request async notification 
	// 
	nRet = WSAEventSelect(m_hSocket, 
						  m_hEvent, 
						  FD_CONNECT|FD_CLOSE|FD_READ); 
	 
	if (nRet == SOCKET_ERROR) 
	{ 
		closesocket(m_hSocket); 
 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
 
 
void CSocketClass::SendData(CString strData) 
{ 
	EnterCriticalSection(&m_criticalSection); 
 
	CString strHdr; 
	CString strPkt; 
 
 
	int nSize = strData.GetLength(); 
 
	m_sendBuff.Write((PBYTE) &nSize, sizeof(nSize)); 
	m_sendBuff.Write((PBYTE) strData.GetBuffer(nSize), nSize); 
 
	DoAsyncSendBuff(); 
	LeaveCriticalSection(&m_criticalSection); 
} 
 
 
 
void CSocketClass::DoAsyncSendBuff() 
{ 
	 
	int nSendDataLen = m_sendBuff.GetBufferLen(); 
	PBYTE pData = m_sendBuff.GetBuffer(); 
 
	 
	m_nBytesSent = 0; 
	 
	while (m_nBytesSent < nSendDataLen)   
	{ 
		int nBytes; 
 
		if ((nBytes = send(m_hSocket, (LPCTSTR)pData, nSendDataLen - m_nBytesSent,0)) 
			== SOCKET_ERROR) 
		{ 
			if (GetLastError() == WSAEWOULDBLOCK)  
			{ 
				TRACE("Blocking\n"); 
				Sleep(100); 
				break; 
			} 
			else 
			{ 
				TCHAR szError[256]; 
				wsprintf(szError, _TEXT("Server Socket failed to send: %d"), GetLastError()); 
				 
				closesocket(m_hSocket); 
								 
				m_nBytesSent = 0;				 
				return; 
			} 
		} 
		else 
		{ 
			m_nBytesSent += nBytes; 
			m_sendBuff.Delete(nBytes); 
		} 
	} 
}