⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asyncsocketex.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				}
				delete pMsg;
				return 0;
			}
	#endif //NOLAYERS
			else if (message == WM_SOCKETEX_GETHOST)
			{
				//WSAAsyncGetHostByName reply

				//Verify parameters
				ASSERT(hWnd);
				CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLong(hWnd, GWL_USERDATA);
				ASSERT(pWnd);

				CAsyncSocketEx *pSocket = NULL;
				for (int i=0; i<pWnd->m_nWindowDataSize; i++)
				{
					pSocket = pWnd->m_pAsyncSocketExWindowData[i].m_pSocket;
					if (pSocket && pSocket->m_hAsyncGetHostByNameHandle &&
						pSocket->m_hAsyncGetHostByNameHandle == (HANDLE)wParam)
						break;
				}
				if (i == pWnd->m_nWindowDataSize)
					return 0;

				int nErrorCode = lParam >> 16;
				if (nErrorCode)
				{
					pSocket->OnConnect(nErrorCode);
					return 0;
				}

				SOCKADDR_IN sockAddr;
				memset(&sockAddr,0,sizeof(sockAddr));
				sockAddr.sin_family=AF_INET;
				sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr;

				sockAddr.sin_port = htons(pSocket->m_nAsyncGetHostByNamePort);

				BOOL res = pSocket->Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
				delete [] pSocket->m_pAsyncGetHostByNameBuffer;
				pSocket->m_pAsyncGetHostByNameBuffer=0;
				pSocket->m_hAsyncGetHostByNameHandle=0;

				if (!res)
					if (GetLastError()!=WSAEWOULDBLOCK)
						pSocket->OnConnect(GetLastError());
				return 0;
			}
			return DefWindowProc(hWnd, message, wParam, lParam);
#ifdef USE_CLIENT_TCP_CATCH_ALL_HANDLER
		}
		catch(CException* e){
			TCHAR szError[1024];
			e->GetErrorMessage(szError, ARRSIZE(szError));
			const CRuntimeClass* pRuntimeClass = e->GetRuntimeClass();
			LPCSTR pszClassName = (pRuntimeClass) ? pRuntimeClass->m_lpszClassName : NULL;
			if (!pszClassName)
				pszClassName = "CException";
			TRACE(_T("*** Unknown %hs exception in CAsyncSocketExHelperWindow::WindowProc - %s\n"), pszClassName, szError);
			e->Delete();
		}
		catch (...) {
			// TODO: This exception handler should definitively *not* be here. Though we seem to need it to
			// catch some very strange crashs which deal with socket deletion problems in the client's TCP socket.
			TRACE("*** Unknown exception in CAsyncSocketExHelperWindow::WindowProc\n");
			ASSERT(0);
		}
#endif
		return 0;
	}

	HWND CAsyncSocketExHelperWindow::GetHwnd()
	{
		return m_hWnd;
	}

private:
	HWND m_hWnd;
	struct t_AsyncSocketExWindowData
	{
		CAsyncSocketEx *m_pSocket;
	} *m_pAsyncSocketExWindowData;
	int m_nWindowDataSize;
	int m_nWindowDataPos;
	int m_nSocketCount;
};

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CAsyncSocketEx, CObject)

CAsyncSocketEx::CAsyncSocketEx()
{
	m_SocketData.hSocket=INVALID_SOCKET;
	m_SocketData.nSocketIndex=-1;
	m_pLocalAsyncSocketExThreadData=0;
#ifndef NOLAYERS
	m_pFirstLayer=0;
	m_pLastLayer=0;
#endif //NOLAYERS
	m_pAsyncGetHostByNameBuffer = NULL;
	m_hAsyncGetHostByNameHandle = NULL;
}

CAsyncSocketEx::~CAsyncSocketEx()
{
	Close();
	FreeAsyncSocketExInstance();
}

BOOL CAsyncSocketEx::Create( UINT nSocketPort /*=0*/, int nSocketType /*=SOCK_STREAM*/, long lEvent /*=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/, LPCTSTR lpszSocketAddress /*=NULL*/, BOOL bReuseAddr /*=FALSE*/ )
{
	ASSERT(GetSocketHandle()==INVALID_SOCKET);

	//Close the socket, although this should not happen
	if (GetSocketHandle() != INVALID_SOCKET)
	{
		WSASetLastError(WSAEALREADY);
		return FALSE;
	}

	BOOL res=InitAsyncSocketExInstance();
	ASSERT(res);
	if (!res)
	{
		WSASetLastError(WSANOTINITIALISED);
		return FALSE;
	}

#ifndef NOLAYERS
	if (m_pFirstLayer)
		return m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress);
	else
#endif //NOLAYERS
	{
		SOCKET hSocket=socket(AF_INET, nSocketType, 0);
		if (hSocket==INVALID_SOCKET)
			return FALSE;
		m_SocketData.hSocket=hSocket;
		AttachHandle(hSocket);
		if (!AsyncSelect(lEvent))
		{
			Close();
			return FALSE;
		}
#ifndef NOLAYERS
		if (m_pFirstLayer)
		{
			if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) )
			{
				Close();
				return FALSE;
			}
		}
#endif //NOLAYERS

		if (bReuseAddr)
		{
			// Has to be done right before binding the socket!
			int iOptVal = 1;
			VERIFY( SetSockOpt(SO_REUSEADDR, &iOptVal, sizeof iOptVal) );
		}

		if (!Bind(nSocketPort, lpszSocketAddress))
		{
			Close();
			return FALSE;
		}
		return TRUE;
	}
}



void CAsyncSocketEx::OnReceive(int nErrorCode)
{
}

void CAsyncSocketEx::OnSend(int nErrorCode)
{
}

void CAsyncSocketEx::OnConnect(int nErrorCode)
{
}

void CAsyncSocketEx::OnAccept(int nErrorCode)
{
}

void CAsyncSocketEx::OnClose(int nErrorCode)
{
}

BOOL CAsyncSocketEx::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress)
{
	USES_CONVERSION;

	SOCKADDR_IN sockAddr;
	memset(&sockAddr,0,sizeof(sockAddr));

	LPSTR lpszAscii = T2A((LPTSTR)lpszSocketAddress);
	sockAddr.sin_family = AF_INET;

	if (lpszAscii == NULL)
		sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	else
	{
		DWORD lResult = inet_addr(lpszAscii);
		if (lResult == INADDR_NONE)
		{
			WSASetLastError(WSAEINVAL);
			return FALSE;
		}
		sockAddr.sin_addr.s_addr = lResult;
	}

	sockAddr.sin_port = htons((u_short)nSocketPort);

	return Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr));
}

BOOL CAsyncSocketEx::Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
	if (!bind(m_SocketData.hSocket, lpSockAddr, nSockAddrLen))
		return TRUE;
	else
		return FALSE;
}

void CAsyncSocketEx::AttachHandle(SOCKET hSocket)
{
	ASSERT(m_pLocalAsyncSocketExThreadData);
	VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->AddSocket(this, m_SocketData.nSocketIndex));
}

void CAsyncSocketEx::DetachHandle(SOCKET hSocket)
{
	ASSERT(m_pLocalAsyncSocketExThreadData);
	if (!m_pLocalAsyncSocketExThreadData)
		return;
	ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);
	if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)
		return;
	VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->RemoveSocket(this, m_SocketData.nSocketIndex));
}

void CAsyncSocketEx::Close()
{
#ifndef NOLAYERS
	if (m_pFirstLayer)
		m_pFirstLayer->Close();
#endif //NOLAYERS
	if (m_SocketData.hSocket != INVALID_SOCKET)
	{
		VERIFY(closesocket(m_SocketData.hSocket)!=SOCKET_ERROR);
		DetachHandle(m_SocketData.hSocket);
		m_SocketData.hSocket=INVALID_SOCKET;
	}
#ifndef NOLAYERS
	RemoveAllLayers();
#endif //NOLAYERS
	delete [] m_pAsyncGetHostByNameBuffer;
	m_pAsyncGetHostByNameBuffer = NULL;
	if (m_hAsyncGetHostByNameHandle)
		WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle);
	m_hAsyncGetHostByNameHandle = NULL;
}

BOOL CAsyncSocketEx::InitAsyncSocketExInstance()
{
	//Check if already initialized
	if (m_pLocalAsyncSocketExThreadData)
		return TRUE;

	DWORD id=GetCurrentThreadId();

	BOOL bResult = TRUE;
	m_sGlobalCriticalSection.Lock();

	try{
	    //Get thread specific data
	    if (m_spAsyncSocketExThreadDataList)
	    {
		    t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;
		    while (pList)
		    {
			    ASSERT(pList->pThreadData);
			    ASSERT(pList->pThreadData->nInstanceCount>0);
    
			    if (pList->pThreadData->nThreadId==id)
			    {
				    m_pLocalAsyncSocketExThreadData=pList->pThreadData;
				    m_pLocalAsyncSocketExThreadData->nInstanceCount++;
				    break;
			    }
			    pList=pList->pNext;
		    }
		    //Current thread yet has no sockets
		    if (!pList)
		    {
			    //Initialize data for current thread
			    pList=new t_AsyncSocketExThreadDataList;
			    pList->pNext=m_spAsyncSocketExThreadDataList;
			    m_spAsyncSocketExThreadDataList=pList;
			    m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;
			    m_pLocalAsyncSocketExThreadData->nInstanceCount=1;
			    m_pLocalAsyncSocketExThreadData->nThreadId=id;
			    m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow;
			    m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;
		    }
	    }
	    else
	    {	//No thread has instances of CAsyncSocketEx; Initialize data
		    m_spAsyncSocketExThreadDataList=new t_AsyncSocketExThreadDataList;
		    m_spAsyncSocketExThreadDataList->pNext=0;
		    m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;
		    m_pLocalAsyncSocketExThreadData->nInstanceCount=1;
		    m_pLocalAsyncSocketExThreadData->nThreadId=id;
		    m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow;
		    m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;
	    }
	}
	catch(...){
		TRACE("Unknown exception in CAsyncSocketEx::InitAsyncSocketExInstance()\n");
		ASSERT(0);
		bResult = FALSE;
	}

	m_sGlobalCriticalSection.Unlock();

	return bResult;
}

void CAsyncSocketEx::FreeAsyncSocketExInstance()
{
	//Check if already freed
	if (!m_pLocalAsyncSocketExThreadData)
		return;

	DWORD id=m_pLocalAsyncSocketExThreadData->nThreadId;
	m_sGlobalCriticalSection.Lock();

	try{
	    ASSERT(m_spAsyncSocketExThreadDataList);
	    t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;
	    t_AsyncSocketExThreadDataList *pPrev=0;
    
	    //Serach for data for current thread and decrease instance count
	    while (pList)
	    {
		    ASSERT(pList->pThreadData);
		    ASSERT(pList->pThreadData->nInstanceCount>0);
    
		    if (pList->pThreadData->nThreadId==id)
		    {
			    ASSERT(m_pLocalAsyncSocketExThreadData==pList->pThreadData);
			    m_pLocalAsyncSocketExThreadData->nInstanceCount--;
    
			    //Freeing last instance?
			    //If so, destroy helper window
			    if (!m_pLocalAsyncSocketExThreadData->nInstanceCount)
			    {
				    delete m_pLocalAsyncSocketExThreadData->m_pHelperWindow;
				    delete m_pLocalAsyncSocketExThreadData;
				    if (pPrev)
					    pPrev->pNext=pList->pNext;
				    else
					    m_spAsyncSocketExThreadDataList=pList->pNext;
				    delete pList;
				    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -