回调函数实例

class CAsyncSocketExHelperWindow
{
public:
 CAsyncSocketExHelperWindow()
 {
  //Initialize data
  m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets
  memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));
  m_nWindowDataSize = 512;
  m_nSocketCount = 0;
  m_nWindowDataPos = 0;

  //Create window
  WNDCLASSEX wndclass;
  wndclass.cbSize = sizeof wndclass;
  wndclass.style = 0;
  wndclass.lpfnWndProc = WindowProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hInstance = GetModuleHandle(0);
  wndclass.hIcon = 0;
  wndclass.hCursor = 0;
  wndclass.hbrBackground = 0;
  wndclass.lpszMenuName = 0;
  wndclass.lpszClassName = _T("CAsyncSocketEx Helper Window");
  wndclass.hIconSm = 0;
  RegisterClassEx(&wndclass);

  m_hWnd = CreateWindow(_T("CAsyncSocketEx Helper Window"), _T("CAsyncSocketEx Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
  ASSERT( m_hWnd );
  SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
 };

 virtual ~CAsyncSocketExHelperWindow()
 {
  //Clean up socket storage
  delete[] m_pAsyncSocketExWindowData;
  m_pAsyncSocketExWindowData = 0;
  m_nWindowDataSize = 0;
  m_nSocketCount = 0;

  //Destroy window
  if (m_hWnd)
  {
   DestroyWindow(m_hWnd);
   m_hWnd = 0;
  }
 }

 //Adds a socket to the list of attached sockets
 BOOL AddSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
 {
  ASSERT( pSocket );
  if (!m_nWindowDataSize)
  {
   ASSERT( !m_nSocketCount );
   m_nWindowDataSize = 512;
   m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets
   memset(m_pAsyncSocketExWindowData, 0, 512 * sizeof(t_AsyncSocketExWindowData));
  }

  if (nSocketIndex != -1)
  {
   ASSERT( m_pAsyncSocketExWindowData );
   ASSERT( m_nWindowDataSize>nSocketIndex );
   ASSERT( m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket == pSocket );
   ASSERT( m_nSocketCount );
   return TRUE;
  }

  //Increase socket storage if too small
  if (m_nSocketCount >= m_nWindowDataSize - 10)
  {
   int nOldWindowDataSize = m_nWindowDataSize;
   ASSERT( m_nWindowDataSize < MAX_SOCKETS );
   m_nWindowDataSize += 512;
   if (m_nWindowDataSize > MAX_SOCKETS)
    m_nWindowDataSize = MAX_SOCKETS;

   t_AsyncSocketExWindowData* tmp = m_pAsyncSocketExWindowData;
   m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[m_nWindowDataSize];
   memcpy(m_pAsyncSocketExWindowData, tmp, nOldWindowDataSize * sizeof(t_AsyncSocketExWindowData));
   memset(m_pAsyncSocketExWindowData + nOldWindowDataSize, 0, (m_nWindowDataSize - nOldWindowDataSize) * sizeof(t_AsyncSocketExWindowData));
   delete[] tmp;
  }

  //Search for free slot
  for (int i = m_nWindowDataPos; i < m_nWindowDataSize + m_nWindowDataPos; i++)
  {
   if (m_pAsyncSocketExWindowData[i % m_nWindowDataSize].m_pSocket == NULL)
   {
    m_pAsyncSocketExWindowData[i % m_nWindowDataSize].m_pSocket = pSocket;
    nSocketIndex = i % m_nWindowDataSize;
    m_nWindowDataPos = (i + 1) % m_nWindowDataSize;
    m_nSocketCount++;
    return TRUE;
   }
  }

  //No slot found, maybe there are too much sockets!
  return FALSE;
 }

 //Removes a socket from the socket storage
 BOOL RemoveSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
 {
  UNREFERENCED_PARAMETER(pSocket);
  ASSERT( pSocket );

  if (nSocketIndex == -1)
   return TRUE;

  ASSERT( m_pAsyncSocketExWindowData );
  ASSERT( m_nWindowDataSize > 0 );
  ASSERT( m_nSocketCount > 0 );
  ASSERT( m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket == pSocket );
  m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket = 0;
  nSocketIndex = -1;
  m_nSocketCount--;

  return TRUE;
 }

 //Processes event notifications sent by the sockets or the layers
 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
#if !NO_USE_CLIENT_TCP_CATCH_ALL_HANDLER
  try
  {
#endif//!NO_USE_CLIENT_TCP_CATCH_ALL_HANDLER
   if (message >= WM_SOCKETEX_NOTIFY)
   {
    //Verify parameters
    ASSERT( hWnd );
    CAsyncSocketExHelperWindow *pWnd = (CAsyncSocketExHelperWindow *)GetWindowLong(hWnd, GWL_USERDATA);
    ASSERT( pWnd );

    if (message < (UINT)(WM_SOCKETEX_NOTIFY + pWnd->m_nWindowDataSize)) //Index is within socket storage
    {
     //Lookup socket and verify if it's valid
     CAsyncSocketEx *pSocket = pWnd->m_pAsyncSocketExWindowData[message - WM_SOCKETEX_NOTIFY].m_pSocket;
     SOCKET hSocket = wParam;
     if (!pSocket)
      return 0;
     if (hSocket == INVALID_SOCKET)
      return 0;
     if (pSocket->m_SocketData.hSocket != hSocket)
      return 0;

     int nEvent = lParam & 0xFFFF;
     int nErrorCode = lParam >> 16;

     //Dispatch notification
 #ifndef NOLAYERS
     if (!pSocket->m_pFirstLayer)
     {
 #endif //NOLAYERS
      //Dispatch to CAsyncSocketEx instance
      switch (nEvent)
      {
       case FD_READ:
       {
        DWORD nBytes;
        if (!pSocket->IOCtl(FIONREAD, &nBytes))
         nErrorCode = WSAGetLastError();
        if (nBytes != 0 || nErrorCode != 0)
         pSocket->OnReceive(nErrorCode);
        break;
       }
       case FD_FORCEREAD: //Forceread does not check if there's data waiting
        pSocket->OnReceive(nErrorCode);
        break;
       case FD_WRITE:
        pSocket->OnSend(nErrorCode);
        break;
       case FD_CONNECT:
        pSocket->OnConnect(nErrorCode);
        break;
       case FD_ACCEPT:
        pSocket->OnAccept(nErrorCode);
        break;
       case FD_CLOSE:
        pSocket->OnClose(nErrorCode);
        break;
      }
     }
 #ifndef NOLAYERS
     else //Dispatch notification to the lowest layer
     {
      if (nEvent == FD_READ)
      {
       DWORD nBytes;
       if (!pSocket->IOCtl(FIONREAD, &nBytes))
        nErrorCode = WSAGetLastError();
       if (nBytes != 0 || nErrorCode != 0)
        pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
      }
      else
       pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
     }
    }
 #endif //NOLAYERS
    return 0;
   }
 #ifndef NOLAYERS
   else if (message == WM_SOCKETEX_TRIGGER) //Notification event sent by a layer
   {
    //Verify parameters, lookup socket and notification message
    if (!wParam)
     return 0;
    CAsyncSocketEx *pSocket = (CAsyncSocketEx *)wParam;
    CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg = (CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam;
    if (pSocket->m_SocketData.hSocket == INVALID_SOCKET) {
     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 socket class
     switch (nEvent)
     {
      case FD_READ:
       if (pSocket->m_lEvent & FD_READ)
        pSocket->OnReceive(nErrorCode);
       break;
      case FD_FORCEREAD:
       if (pSocket->m_lEvent & FD_FORCEREAD)
        pSocket->OnReceive(nErrorCode);
       break;
      case FD_WRITE:
       if (pSocket->m_lEvent & FD_WRITE)
        pSocket->OnSend(nErrorCode);
       break;
      case FD_CONNECT:
       if (pSocket->m_lEvent & FD_CONNECT)
        pSocket->OnConnect(nErrorCode);
       break;
      case FD_ACCEPT:
       if (pSocket->m_lEvent & FD_ACCEPT)
        pSocket->OnAccept(nErrorCode);
       break;
      case FD_CLOSE:
       if (pSocket->m_lEvent & FD_CLOSE)
        pSocket->OnClose(nErrorCode);
       break;
     }
    }
    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;
    int i;
    for (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 = {0};
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr;
    sockAddr.sin_port = htons((u_short)pSocket->m_nAsyncGetHostByNamePort);

    if (!pSocket->OnHostNameResolved(&sockAddr))
    {
     return 0;
    }

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

    if (!res && GetLastError() != WSAEWOULDBLOCK)
     pSocket->OnConnect(GetLastError());

    return 0;
   }
   return DefWindowProc(hWnd, message, wParam, lParam);
#if !NO_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);
  }
  return 0;
#endif//!NO_USE_CLIENT_TCP_CATCH_ALL_HANDLER
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值