asyncsocketex.cpp

来自「一个FTP下载的源代码。代码质量非常高」· C++ 代码 · 共 1,298 行 · 第 1/3 页

CPP
1,298
字号
			
			//Dispatch to layer
			if (pMsg->pLayer)
				pMsg->pLayer->CallEvent(nEvent, nErrorCode);
			else
			{
				//Dispatch to CAsyncSocketEx instance
				switch (nEvent)
				{
				case FD_READ:
#ifndef NOSOCKETSTATES
					if (pSocket->GetState() == connecting && !nErrorCode)
					{
						pSocket->m_nPendingEvents |= FD_READ;
						break;
					}
					else if (pSocket->GetState() == attached && !nErrorCode)
						pSocket->SetState(connected);
					if (pSocket->GetState() != connected)
						break;
#endif //NOSOCKETSTATES
					if (pSocket->m_lEvent & FD_READ)
					{
#ifndef NOSOCKETSTATES
						if (nErrorCode)
							pSocket->SetState(aborted);
#endif //NOSOCKETSTATES
						pSocket->OnReceive(nErrorCode);
					}
					break;
				case FD_FORCEREAD: //Forceread does not check if there's data waiting
#ifndef NOSOCKETSTATES
					if (pSocket->GetState() == connecting && !nErrorCode)
					{
						pSocket->m_nPendingEvents |= FD_FORCEREAD;
						break;
					}
					else if (pSocket->GetState() == attached && !nErrorCode)
						pSocket->SetState(connected);
					if (pSocket->GetState() != connected)
						break;
#endif //NOSOCKETSTATES
					if (pSocket->m_lEvent & FD_READ)
					{
#ifndef NOSOCKETSTATES
						if (nErrorCode)
							pSocket->SetState(aborted);
#endif //NOSOCKETSTATES
						pSocket->OnReceive(nErrorCode);
					}
					break;
				case FD_WRITE:
#ifndef NOSOCKETSTATES
					if (pSocket->GetState() == connecting && !nErrorCode)
					{
						pSocket->m_nPendingEvents |= FD_WRITE;
						break;
					}
					else if (pSocket->GetState() == attached && !nErrorCode)
						pSocket->SetState(connected);
					if (pSocket->GetState() != connected)
						break;
#endif //NOSOCKETSTATES
					if (pSocket->m_lEvent & FD_WRITE)
					{
#ifndef NOSOCKETSTATES
						if (nErrorCode)
							pSocket->SetState(aborted);
#endif //NOSOCKETSTATES
						pSocket->OnSend(nErrorCode);
					}
					break;
				case FD_CONNECT:
#ifndef NOSOCKETSTATES
					if (pSocket->GetState() == connecting)
						pSocket->SetState(connected);
					else if (pSocket->GetState() == attached && !nErrorCode)
						pSocket->SetState(connected);
#endif //NOSOCKETSTATES
					if (pSocket->m_lEvent & FD_CONNECT)
						pSocket->OnConnect(nErrorCode);
#ifndef NOSOCKETSTATES
					if (!nErrorCode)
					{
						if (((pSocket->m_nPendingEvents&FD_READ) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_READ))
							pSocket->OnReceive(0);
						if (((pSocket->m_nPendingEvents&FD_FORCEREAD) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_READ))
							pSocket->OnReceive(0);
						if (((pSocket->m_nPendingEvents&FD_WRITE) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_WRITE))
							pSocket->OnSend(0);
					}
					pSocket->m_nPendingEvents = 0;
#endif //NOSOCKETSTATES
					break;
				case FD_ACCEPT:
#ifndef NOSOCKETSTATES
					if ((pSocket->GetState() == listening || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_ACCEPT))
#endif //NOSOCKETSTATES
					{
						pSocket->OnAccept(nErrorCode);
					}
					break;
				case FD_CLOSE:
#ifndef NOSOCKETSTATES
					if ((pSocket->GetState() == connected || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_CLOSE))
					{
						pSocket->SetState(nErrorCode?aborted:closed);
#else
					{
#endif //NOSOCKETSTATES
						pSocket->OnClose(nErrorCode);
					}
					break;
				}
			}
			delete pMsg;
			return 0;
		}
#endif //NOLAYERS
		else if (message == WM_USER+1)
		{
			//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 (!pSocket)
				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);
	}

	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
//////////////////////////////////////////////////////////////////////

CAsyncSocketEx::CAsyncSocketEx()
{
	m_SocketData.hSocket=INVALID_SOCKET;
	m_SocketData.nSocketIndex=-1;
	m_pLocalAsyncSocketExThreadData=0;

#ifndef NOSOCKETSTATES
	m_nPendingEvents = 0;
	m_nState = notsock;
#endif //NOSOCKETSTATES

#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*/ )
{
	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)
	{
		BOOL res = m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress);
#ifndef NOSOCKETSTATES
		if (res)
			SetState(unconnected);
#endif //NOSOCKETSTATES
		return res;
	}
	else
#endif //NOLAYERS
	{
		SOCKET hSocket=socket(AF_INET, nSocketType, 0);
		if (hSocket==INVALID_SOCKET)
			return FALSE;
		m_SocketData.hSocket=hSocket;
		AttachHandle(hSocket);
		
#ifndef NOLAYERS
		if (m_pFirstLayer)
		{
			m_lEvent = lEvent;
			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;
			}
		}
		else
#endif //NOLAYERS
		{
			if (!AsyncSelect(lEvent))
			{
				Close();
				return FALSE;
			}
		}

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

#ifndef NOSOCKETSTATES
		SetState(unconnected);
#endif //NOSOCKETSTATES
		
		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));
#ifndef NOSOCKETSTATES
	SetState(attached);
#endif //NOSOCKETSTATES
}

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));
#ifndef NOSOCKETSTATES
	SetState(notsock);
#endif //NOSOCKETSTATES
}

void CAsyncSocketEx::Close()
{
#ifndef NOSOCKETSTATES
	m_nPendingEvents = 0;
#endif //NOSOCKETSTATES
#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();

	m_sGlobalCriticalSection.Lock();

	//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;

⌨️ 快捷键说明

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