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

📄 wsasimpl.c

📁 windows 网络编程。pdf文档
💻 C
📖 第 1 页 / 共 2 页
字号:
            /* Release timer, if there is one */
            KillTimer (lpstConn->hwnd, TIMEOUT_ID);
          break;
        }
        if (lpstConn->nTimeout) {
          /* Reset timer, if there is one */
          SetTimer(hWinMain, TIMEOUT_ID, lpstConn->nTimeout, 0L);
        }
      } else {
        /* If receive failed, return an error */
        cbTotalRcvd = SOCKET_ERROR;
      }
    }
    /* Unsubclass active window before we leave */
    SetWindowLong(lpstConn->hwnd, GWL_WNDPROC, (long)lpstConn->lpfnWndProc);
    lpstConn->nTimeout = 0;  /* reset timer */
  }
  return (cbTotalRcvd);
} /* end RecvData() */

/*--------------------------------------------------------------
 * Function: DoRecv()
 *
 * Description: Receive data into buffer.  We call this function
 *  in response to FD_READ asynchronous notification. 
 */
int DoRecv(SOCKET hSock, LPSTR lpInBuf, int cbTotalToRecv,
  LPCONNDATA lpstConn)
{
  int cbTotalRcvd = 0;
  int cbLeftToRecv = cbTotalToRecv;
  int nRet=0, WSAErr;

  /* Read as much as we can buffer from client */
  while (cbLeftToRecv > 0) {

    nRet = recv (hSock,lpInBuf+cbTotalRcvd, cbLeftToRecv, 0);
    if (nRet == SOCKET_ERROR) {
      WSAErr = WSAGetLastError();
      /* Display all errors except "operation interrupted" */
      if (WSAErr != WSAEINTR) {
        WSAperror(WSAErr, (LPSTR)"recv()", hInst);
        /*  unsubclass first so user can respond to error) */
        SetWindowLong(lpstConn->hwnd,GWL_WNDPROC,
	   (DWORD)lpstConn->lpfnWndProc);
      }
      break;
    } else if (nRet == 0) { /* Other side closed socket */
      /* quit if server closed connection */
      break;
    } else {
      /* Update byte counter */
      cbTotalRcvd += nRet;
    }
    cbLeftToRecv = cbTotalToRecv - cbTotalRcvd;
  }
  return (cbTotalRcvd);
} /* end DoRecv() */

/*--------------------------------------------------------------
 * Function: CloseTCP()
 *
 * Description: Do a graceful close of a TCP connection using 
 *  the robust algorithm of "half-closing" with shutdown(how=1),
 *  then loop on recv() to read remaining data until it fails,
 *  or returns a zero, then call closesocket().
 */
int WINAPI CloseTCP(SOCKET hSock, LPSTR lpInBuf, int len)
{
  int nRet = SOCKET_ERROR, cbBytesDone=0;
  LPCONNDATA lpstConn;
 
  lpstConn = FindConn(hSock, 0);
  if (!lpstConn) {
    /* Socket not found, so it's not valid */
    WSASetLastError(WSAENOTSOCK);
  } else {
    if (WSAIsBlocking()) {
      /* Can't close socket now since blocking operation pending,
       *  so just cancel the blocking operation and we'll close
       *  connection when pending operation fails with WSAEINTR */
       WSACancelBlockingCall();
    } else {
      /* Signal the end is near */
      lpstConn->hSock = INVALID_SOCKET;
         
      /* Half-close the connection to close neatly (we ignore the error here
       *  since some WinSocks fail with WSAEINVAL if they've recieved a RESET
       *  on the socket before the call to shutdown(). */
      nRet = shutdown (hSock, 1);
    
      /* Read and discard remaining data (until EOF or any error) */
      nRet = 1;
      while (nRet && (nRet != SOCKET_ERROR)) {
          nRet = recv (hSock, lpInBuf, len-cbBytesDone, 0);
          if (nRet > 0)
            cbBytesDone += nRet;
      }
    
      /* close the socket, and ignore any error (since we can't do much 
       *  about them anyway */
      nRet = closesocket (hSock);
    }
    RemoveConn(lpstConn);
  }
  return (nRet);
} /* end CloseTCP() */

/*---------------------------------------------------------------
 * Function:NewConn()
 *
 * Description: Create a new socket structure and put in list
 */
LPCONNDATA NewConn (SOCKET hSock,PSOCKADDR_IN lpstRmtName) {
  int nAddrSize = sizeof(SOCKADDR);
  LPCONNDATA lpstConnTmp;
  LPCONNDATA lpstConn = (LPCONNDATA)0;
  HLOCAL hConnData;

  /* Allocate memory for the new socket structure */
  hConnData = LocalAlloc (LMEM_ZEROINIT, sizeof(CONNDATA));
  
  if (hConnData) {
    /* Lock it down and link it into the list */
    lpstConn = (LPCONNDATA) LocalLock(hConnData);
    
    if (!lpstConnHead) {
      lpstConnHead = lpstConn;// BQ NOTE: This Doesn't Work for some reason!
    } else {
      for (lpstConnTmp = lpstConnHead; 
           lpstConnTmp && lpstConnTmp->lpstNext; 
           lpstConnTmp = lpstConnTmp->lpstNext);
      lpstConnTmp->lpstNext = lpstConn;
    }
    /* Initialize socket structure */
    lpstConn->hSock = hSock;
    _fmemcpy ((LPSTR)&(lpstConn->stRmtName), 
              (LPSTR)lpstRmtName, sizeof(SOCKADDR));
  }
  return (lpstConn);
} /* end NewConn() */  

/*---------------------------------------------------------------
 * Function: FindConn()
 *
 * Description: Find socket structure for connection using 
 *  either socket or window as search key.
 */
LPCONNDATA FindConn (SOCKET hSock, HWND hwnd) {
  LPCONNDATA lpstConnTmp;
  
  for (lpstConnTmp = lpstConnHead; 
       lpstConnTmp;     
       lpstConnTmp = lpstConnTmp->lpstNext) {
    if (hSock) {
      if (lpstConnTmp->hSock == hSock)
        break;
    } else if (lpstConnTmp->hwnd == hwnd) {
      break;
    }
  }
  return (lpstConnTmp);
} /* end FindConn() */  

/*---------------------------------------------------------------
 * Function: RemoveConn()
 *
 * Description: Free the memory for socket structure
 */
void RemoveConn (LPCONNDATA lpstConn) {
  LPCONNDATA lpstConnTmp;
  HLOCAL hConnTmp;
  
  if (lpstConn == lpstConnHead) {
    lpstConnHead = lpstConn->lpstNext;
  } else {  
    for (lpstConnTmp = lpstConnHead; 
         lpstConnTmp;
         lpstConnTmp = lpstConnTmp->lpstNext) {
      if (lpstConnTmp->lpstNext == lpstConn) {
        lpstConnTmp->lpstNext = lpstConn->lpstNext;
      }
    }     
  }
  RemoveTask (lpstConn->lpstTask);
  hConnTmp = LocalHandle((void NEAR*)lpstConn);
  LocalUnlock (hConnTmp);
  LocalFree (hConnTmp);
} /* end RemoveConn() */  

/*---------------------------------------------------------------
 * Function: NewTask()
 *
 * Description: Register task with WinSock DLL by calling 
 *  WSAStartup(), and create a new Task structure
 */
LPTASKDATA NewTask (HTASK hTask)
{ 
  HANDLE hTaskData;
  LPTASKDATA lpstTask = (LPTASKDATA)0L;
  int nRet;

  /* Register task with WinSock DLL */
  nRet = WSAStartup(WSA_VERSION, &stWSAData);
  if (nRet != 0) {
    WSAperror(nRet, "WSAStartup()", hInst);
  } else {
    /* Allocate memory for a window structure */
    hTaskData = 
      LocalAlloc(LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof(TASKDATA));
    if (hTaskData) {
  
      /* Convert it to a pointer */
      lpstTask = (LPTASKDATA) LocalLock (hTaskData);
      if (lpstTask) {
      
        /* Initialize structure */
        lpstTask->hTask = hTask;
        lpstTask->nRefCount = 1;
      
        /* Link this new record into our linked list */
        if (!lpstTaskHead) {
          lpstTaskHead = lpstTask;
        } else {
          LPTASKDATA lpstTaskTmp;
          for (lpstTaskTmp = lpstTaskHead;
               lpstTaskTmp->lpstNext;
               lpstTaskTmp = lpstTaskTmp->lpstNext);
          lpstTaskTmp->lpstNext = lpstTask;
        }
      } else {
        /* Set error to indicate memory problems, and free memory */
        WSASetLastError(WSAENOBUFS);
        LocalFree(hTaskData);
      }
    } else {
      /* Set error to indicate we couldn't allocate memory */
      WSASetLastError(WSAENOBUFS);
    }
  }
  return (lpstTask);
} /* end NewTask() */

/*---------------------------------------------------------------
 * Function: FindTask()
 *
 * Description: Find Task structure using task handle as key.
 */
LPTASKDATA FindTask (HTASK hTask) {
  LPTASKDATA lpstTaskTmp;
  
  for (lpstTaskTmp = lpstTaskHead; 
       lpstTaskTmp;     
       lpstTaskTmp = lpstTaskTmp->lpstNext) {
    if (lpstTaskTmp->hTask == hTask)
      break;
  }
  return (lpstTaskTmp);
} /* end FindTask() */  

/*---------------------------------------------------------------
 * Function: RemoveTask()
 *
 * Description: Decrement the task reference count, and free 
 *  the memory for task structure when ref count is zero.
 */
void RemoveTask (LPTASKDATA lpstTask) {
  LPTASKDATA lpstTaskTmp;
  HLOCAL hTaskTmp;
  
  lpstTask->nRefCount--;
  if (lpstTask->nRefCount <= 0) {
    /* Reference count is zero, so free the task structure */
    if (lpstTask == lpstTaskHead) {
      lpstTaskHead = lpstTask->lpstNext;
    } else {  
      for (lpstTaskTmp = lpstTaskHead; 
           lpstTaskTmp;
           lpstTaskTmp = lpstTaskTmp->lpstNext) {
        if (lpstTaskTmp->lpstNext == lpstTask)
          lpstTaskTmp->lpstNext = lpstTask->lpstNext;
      }     
    }
    hTaskTmp = LocalHandle((void NEAR*)lpstTask);
    LocalUnlock (hTaskTmp);
    LocalFree (hTaskTmp);
    
    /* Lastly, call WSACleanup() to deregister task with WinSock */
    WSACleanup();
  }
} /* end RemoveTask() */  

#if 0
/*---------------------------------------------------------------
 * Function: WSAperror()
 *
 * Description:
 */
void WSAperror (int WSAErr, LPSTR szFuncName, HANDLE hInst) 
{
    static char achErrBuf [ERR_SIZE];	/* buffer for errors */
    static char achErrMsg [ERR_SIZE/2];

    WSAErrStr (WSAErr, (LPSTR)achErrMsg, hInst);
    
	wsprintf (achErrBuf, "%s failed,%-40c\n\n%s",
	  (LPSTR)szFuncName,' ',(LPSTR)achErrMsg);
            
	/* Display error message as is (even if incomplete) */
    MessageBox (GetActiveWindow(), (LPSTR)achErrBuf, (LPSTR)"Error", 
    			MB_OK | MB_ICONHAND);
    return;
}  /* end WSAperror() */

/*-----------------------------------------------------------
 * Function: WSAErrStr()
 *
 * Description: Given a WinSock error value, return error string
 *  NOTE: This function requires an active window to work if the
 *  instance handle is not passed.
 */
int WSAErrStr (int WSAErr, LPSTR lpErrBuf, HANDLE hInst) {
    int err_len=0;
    HWND hwnd;
    
    if (!hInst) {
      hwnd  = GetActiveWindow();
#ifndef WIN32
      hInst = GetWindowWord(hwnd, GWW_HINSTANCE);
#else
      hInst = (HANDLE) GetWindowLong(hwnd, GWL_HINSTANCE);
#endif
    }
    
    if (WSAErr == 0)           /* If error passed is 0, use the */
      WSAErr = WSABASEERR;     /*  base resource file number */
            
    if (WSAErr >= WSABASEERR)  /* Valid Error code? */
	  /* get error string from the table in the Resource file */
      err_len = LoadString(hInst, WSAErr, (LPSTR)lpErrBuf, ERR_SIZE/2);
    
    return (err_len);
}  /* end GetWSAErrStr() */

/*-----------------------------------------------------------
 * Function: GetAddr()
 *
 * Description: Given a string, it will return an IP address.
 *   - first it tries to convert the string directly
 *   - if that fails, it tries o resolve it as a hostname
 *
 * WARNING: gethostbyname() is a blocking function
 */
u_long GetAddr (LPSTR szHost) {
  LPHOSTENT lpstHost;
  u_long lAddr = INADDR_ANY;
  
  /* check that we have a string */
  if (*szHost) {
  
    /* check for a dotted-IP address string */
    lAddr = inet_addr (szHost);
  
    /* If not an address, then try to resolve it as a hostname */
    if ((lAddr == INADDR_NONE) &&
        (_fstrcmp (szHost, "255.255.255.255"))) {
      
      lpstHost = gethostbyname(szHost);
      if (lpstHost) {  /* success */
        lAddr = *((u_long FAR *) (lpstHost->h_addr));
      } else {  
        lAddr = INADDR_ANY;   /* failure */
      }
    }
  }
  return (lAddr); 
} /* end GetAddr() */

/*---------------------------------------------------------------
 * Function: GetPort()
 *
 * Description: Return a port number (in network order) from a 
 *  string.  May involve converting from ASCII to integer, or 
 *  resolving as service name.
 *
 * NOTE: This function is limited in several respects:
 *  1) it assumes the service name will not begin with an integer, 
 *     although it *is* possible.
 *  2) it assumes that the port number will be the same for both
 *     tcp & udp (it doesn't specify a protocol in getservbyname()).
 *  3) if it fails, there must be an active window to allow
 *     WSAperror() to display the error text.
 */
u_short GetPort (LPSTR szService)
{
  u_short nPort = 0;  /* Port 0 is invalid */
  LPSERVENT lpServent;
  char c;
  
  c = *szService;
  if ((c>='1') && (c<='9')) {
    /* Convert ASCII to integer, and put in network order */
    nPort = htons((u_short)atoi (szService));
  } else {
    /* Resolve service name to a port number */
    lpServent = getservbyname(szService, 0);
    if (!lpServent) {
      WSAperror (WSAGetLastError(), "getservbyname()", 0);
    } else {
      nPort = lpServent->s_port;
    }
  }
  return (nPort);
} /* end GetPort() */           
#endif

⌨️ 快捷键说明

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