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 + -
显示快捷键?