📄 asyncsocketex.cpp
字号:
{
if (nEvent == FD_READ)
{
// Ignore further FD_READ events after FD_CLOSE has been received
if (pSocket->m_SocketData.onCloseCalled)
return 0;
DWORD nBytes;
if (!pSocket->IOCtl(FIONREAD, &nBytes))
nErrorCode = WSAGetLastError();
if (nBytes != 0 || nErrorCode != 0)
pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
}
else if (nEvent == FD_CLOSE)
{
// If there are still bytes left to read, call OnReceive instead of
// OnClose and trigger a new OnClose
DWORD nBytes = 0;
if (!nErrorCode && pSocket->IOCtl(FIONREAD, &nBytes))
{
if (nBytes > 0)
{
// Just repeat message.
PostMessage(hWnd, message, wParam, lParam);
pSocket->m_SocketData.onCloseCalled = true;
pSocket->m_pLastLayer->CallEvent(FD_READ, 0);
return 0;
}
}
pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
}
else
pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
}
}
#endif //NOLAYERS
return 0;
}
#ifndef NOLAYERS
else if (message == WM_USER) //Notification event sent by a layer
{
//Verify parameters, lookup socket and notification message
//Verify parameters
ASSERT(hWnd);
CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWL_USERDATA);
ASSERT(pWnd);
if (wParam >= static_cast<UINT>(pWnd->m_nWindowDataSize)) //Index is within socket storage
{
return 0;
}
CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;
CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=(CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam;
if (!pMsg || !pSocket || pSocket->m_SocketData.hSocket != pMsg->hSocket)
{
delete pMsg;
return 0;
}
int nEvent=pMsg->lEvent&0xFFFF;
int nErrorCode=pMsg->lEvent>>16;
//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 *)GetWindowLongPtr(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;
}
else if (message == WM_USER + 2)
{
//Verify parameters, lookup socket and notification message
//Verify parameters
if (!hWnd)
return 0;
CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWL_USERDATA);
if (!pWnd)
return 0;
if (wParam >= static_cast<UINT>(pWnd->m_nWindowDataSize)) //Index is within socket storage
return 0;
CAsyncSocketEx *pSocket = pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;
if (!pSocket)
return 0;
// Process pending callbacks
std::list<t_callbackMsg> tmp;
tmp.swap(pSocket->m_pendingCallbacks);
pSocket->OnLayerCallback(tmp);
}
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_SocketData.nFamily = AF_UNSPEC;
m_SocketData.onCloseCalled = false;
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;
m_nSocketPort = 0;
m_lpszSocketAddress = 0;
m_SocketData.addrInfo = 0;
m_SocketData.nextAddr = 0;
}
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*/, int nFamily /*=AF_INET*/)
{
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;
}
m_SocketData.nFamily = nFamily;
#ifndef NOLAYERS
if (m_pFirstLayer)
{
BOOL res = m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress, nFamily);
#ifndef NOSOCKETSTATES
if (res)
SetState(unconnected);
#endif //NOSOCKETSTATES
return res;
}
else
#endif //NOLAYERS
{
if (m_SocketData.nFamily == AF_UNSPEC)
{
#ifndef NOSOCKETSTATES
SetState(unconnected);
#endif //NOSOCKETSTATES
m_lEvent = lEvent;
m_nSocketPort = nSocketPort;
delete [] m_lpszSocketAddress;
if (lpszSocketAddress)
{
m_lpszSocketAddress = new TCHAR[_tcslen(lpszSocketAddress) + 1];
_tcscpy(m_lpszSocketAddress, lpszSocketAddress);
}
else
m_lpszSocketAddress = 0;
return TRUE;
}
else
{
SOCKET hSocket = socket(m_SocketData.nFamily, 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)
{
delete [] m_lpszSocketAddress;
if (lpszSocketAddress)
{
m_lpszSocketAddress = new TCHAR[_tcslen(lpszSocketAddress) + 1];
_tcscpy(m_lpszSocketAddress, lpszSocketAddress);
}
else
m_lpszSocketAddress = 0;
m_nSocketPort = nSocketPort;
if (m_SocketData.nFamily == AF_UNSPEC)
return TRUE;
USES_CONVERSION;
LPSTR lpszAscii = (T2A((LPTSTR)lpszSocketAddress));
if ((m_SocketData.nFamily == AF_INET6 || m_SocketData.nFamily == AF_INET) && lpszAscii)
{
if (!p_getaddrinfo)
{
WSASetLastError(WSAEPROTONOSUPPORT);
return FALSE;
}
addrinfo hints, *res0, *res;
int error;
char port[10];
BOOL ret = FALSE;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = m_SocketData.nFamily;
hints.ai_socktype = SOCK_STREAM;
_snprintf(port, 9, "%lu", nSocketPort);
error = p_getaddrinfo(T2CA(lpszSocketAddress), port, &hints, &res0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -