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

📄 wsasimpl.c

📁 windows 网络编程。pdf文档
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------------
 *
 * Program: WSASIMPL.DLL  Simplified WinSock API (for TCP Clients)
 *
 * filename: wsasimpl.c
 *
 * copyright by Bob Quinn, 1995
 *   
 *  Description:
 *    This DLL provides an "encapsulated WinSock API," as described in
 *    Chapter 12 of _Windows Sockets Network Programming_.  It uses
 *    a helper task. a hidden window and asynchronous operation mode
 *    to provide basic functionality for TCP client applications.
 *
 *  This software is not subject to any  export  provision  of
 *  the  United  States  Department  of  Commerce,  and may be
 *  exported to any country or planet.
 *
 *  Permission is granted to anyone to use this  software  for any  
 *  purpose  on  any computer system, and to alter it and redistribute 
 *  it freely, subject to the following  restrictions:
 *
 *  1. The author is not responsible for the consequences of
 *     use of this software, no matter how awful, even if they
 *     arise from flaws in it.
 *
 *  2. The origin of this software must not be misrepresented,
 *     either by explicit claim or by omission.  Since few users
 *     ever read sources, credits must appear in the documentation.
 *
 *  3. Altered versions must be plainly marked as such, and
 *     must not be misrepresented as being the original software.
 *     Since few users ever read sources, credits must appear in
 *     the documentation.
 *
 *  4. This notice may not be removed or altered.
 *	 
 ---------------------------------------------------------------------*/
#define STRICT
#include "..\wsa_xtra.h"
#include <windows.h>
#include <windowsx.h>

#include <winsock.h>
#include "resource.h"
#include <string.h>   /* for _fmemcpy() */
#include <stdlib.h>   /* for atoi() */
#include "..\winsockx.h"

#define TIMEOUT_ID  WM_USER+1

/*------- important data structures ------*/
typedef struct TaskData {
  HTASK  hTask;                   /* Task ID: primary key */
  int    nRefCount;               /* Number of sockets owned by task */
  struct TaskData *lpstNext;      /* Pointer to next entry in linked list */
} TASKDATA, *PTASKDATA, FAR *LPTASKDATA;

typedef struct ConnData {
  SOCKET hSock;                   /* Conection socket */
  LPTASKDATA lpstTask;            /* Pointer to Task structure */
  HWND   hwnd;                    /* Handle of subclassed window */
  SOCKADDR_IN stRmtName;          /* Remote host address & port */
  int   nTimeout;                 /* Timeout (in millisecs) */
  DWORD lpfnWndProc;              /* Window procedure (before subclassed) */
  struct ConnData *lpstNext;      /* Pointer to next entry in linked list */
} CONNDATA, *PCONNDATA, FAR *LPCONNDATA;

/*-------------- global data -------------*/
char szAppName[] = "wsasimpl";

HWND hWinMain;
HINSTANCE hInst;
 
WSADATA stWSAData;

LPCONNDATA lpstConnHead = 0L;     /* Head of connection data list */
LPTASKDATA lpstTaskHead = 0L;     /* Head of task data list */

/*-------- exported function prototypes ---------*/
int  WINAPI LibMain (HANDLE, WORD, WORD, LPSTR);
LONG CALLBACK SubclassProc (HWND, UINT, WPARAM, LPARAM);
SOCKET WINAPI ConnectTCP(LPSTR, LPSTR);
int WINAPI SendData(SOCKET, LPSTR, int);
int WINAPI RecvData(SOCKET, LPSTR, int, int);
int WINAPI CloseTCP(SOCKET, LPSTR, int);

/*-------- internal function prototypes ---------*/
int DoSend(SOCKET, LPSTR, int, LPCONNDATA);
int DoRecv(SOCKET, LPSTR, int, LPCONNDATA);
LPCONNDATA NewConn (SOCKET, PSOCKADDR_IN);
LPCONNDATA FindConn (SOCKET, HWND);
void      RemoveConn (LPCONNDATA);
LPTASKDATA NewTask (HTASK);
LPTASKDATA FindTask (HTASK);
void      RemoveTask (LPTASKDATA);
u_short GetPort (LPSTR);

/*-------------------------------------------------------------------- 
 *  Function: LibMain()
 *
 *  Description: DLL entry point (we don't have much to do here)
 */
int PASCAL LibMain
  (HANDLE hInstance,
   WORD   wDataSeg,
   WORD   wHeapSize,
   LPSTR  lpszCmdLine)
{
    
    lpszCmdLine = lpszCmdLine; /* avoid warnings */
    wDataSeg    = wDataSeg;
    wHeapSize   = wHeapSize;

    hInst = hInstance;	/* save instance handle */
//    GlobalLock(hInst);

    return (1);
} /* end LibMain() */

/*--------------------------------------------------------------------
 * Function: SubclassProc()
 *
 * Description: process messages bound for calling application to
 *  filter out "reentrant" mouse and keyboard messages while a
 *  blocking network operation is pending.
 */
LONG CALLBACK SubclassProc 
  (HWND hwnd,
   UINT msg,
   WPARAM wParam,
   LPARAM lParam)
{
    LPCONNDATA lpstConn;             /* Work Pointer */
   
    lpstConn = FindConn(0, hwnd);    /* find our socket structure */

    switch (msg) {
      case WM_QUIT:
        /* Close this connection */
        if (lpstConn) {
          CloseTCP(lpstConn->hSock, (LPSTR)0, INPUT_SIZE);
          RemoveConn(lpstConn); 
          /* Release Timer (if it's active) */
          if (lpstConn->nTimeout)
            KillTimer(hwnd, TIMEOUT_ID);
        }
        break;
           
      case WM_CLOSE:
      case WM_TIMER:
        /* If Timeout or Close request, cancel pending */
        if(lpstConn && WSAIsBlocking())
            WSACancelBlockingCall();
        break;
      
      case WM_KEYDOWN:
      case WM_KEYUP:
      case WM_LBUTTONDBLCLK:
      case WM_LBUTTONDOWN:
      case WM_LBUTTONUP:
      case WM_MBUTTONDBLCLK:
      case WM_MBUTTONDOWN:
      case WM_MBUTTONUP:
      case WM_MOUSEACTIVATE:
      case WM_MOUSEMOVE:
      case WM_NCHITTEST:
      case WM_NCLBUTTONDBLCLK:
      case WM_NCLBUTTONDOWN:
      case WM_NCLBUTTONUP:
      case WM_NCMBUTTONDBLCLK:
      case WM_NCMBUTTONDOWN:
      case WM_NCMBUTTONUP:
      case WM_NCMOUSEMOVE:
      case WM_NCRBUTTONDBLCLK:
      case WM_NCRBUTTONDOWN:
      case WM_NCRBUTTONUP:
      case WM_NEXTDLGCTL:
      case WM_RBUTTONDBLCLK:
      case WM_RBUTTONDOWN:
      case WM_RBUTTONUP:
      case WM_SYSCHAR:
      case WM_SYSDEADCHAR:
      case WM_SYSKEYDOWN:
      case WM_SYSKEYUP:
        /* Eat all mouse and keyboard messages */
        return (0L);
        
    default:
        break;
  } /* end switch (msg) */

  if (lpstConn) {  
    /* Let original (pre-subclass) window handler process message */
    return (CallWindowProc ((WNDPROC)(lpstConn->lpfnWndProc),
         hwnd, msg, wParam, lParam));
  } else {
    return (0L);  /* this should never occur */
  }
} /* end SubClassProc() */

/*---------------------------------------------------------------
 * Function: ConnectTCP()
 *
 * Description: get a TCP socket and connect to server (along with
 *  other maintenance stuff, like subclassing window, and registering
 *  task).
 */
SOCKET WINAPI ConnectTCP(LPSTR szDestination, LPSTR szService) 
{
  int nRet;
  HTASK hTask;
  SOCKET hSock;
  LPTASKDATA lpstTask;
  LPCONNDATA lpstConn;
  SOCKADDR_IN stRmtName;

#ifndef WIN32                           
  hTask = GetCurrentTask();     /* Task handle: for our records */
#else
  hTask = GetCurrentProcess();  /* or Process handle (if 32-bit) */
#endif
  lpstTask = FindTask (hTask);
  if (!lpstTask) {
    /* If task isn't registered, then register it (call WSAStartup()) */
    lpstTask = NewTask(hTask);
  }
  if (lpstTask) {
    /* Get a TCP socket */
    hSock = socket (AF_INET, SOCK_STREAM, 0);
    if (hSock == INVALID_SOCKET)  {
      WSAperror(WSAGetLastError(), "socket()", hInst);
    } else {
      /* Get destination address */
      stRmtName.sin_addr.s_addr = GetAddr(szDestination);
      
      if (stRmtName.sin_addr.s_addr != INADDR_NONE) {
        /* Get destination port number */
        stRmtName.sin_port = GetPort(szService);
       
        if (stRmtName.sin_port) {
          /* Create a new socket structure */
          lpstConn = NewConn(hSock, &stRmtName);    

          if (lpstConn) {
            /* Subclass the active window passed 
             *  NOTE: This reveals one limitation in our API.  This is the 
             *  same window we'll subclass during sends and receives, so
             *  we won't capture user I/O if application sends calls the
             *  SendData() or RecvData() from a different window. */
            lpstConn->lpstTask = lpstTask;
            lpstConn->hwnd = GetActiveWindow();
            lpstConn->lpfnWndProc = GetWindowLong(lpstConn->hwnd,GWL_WNDPROC);
            SetWindowLong (lpstConn->hwnd, GWL_WNDPROC, (DWORD)SubclassProc);
          
            /* Initiate non-blocking connect to server */
            stRmtName.sin_family = PF_INET;
            nRet = connect(hSock,(LPSOCKADDR)&stRmtName,SOCKADDR_LEN);
        
            /* Unsubclass active window now that we're done blocking */
            SetWindowLong(lpstConn->hwnd,GWL_WNDPROC,(DWORD)lpstConn->lpfnWndProc);

            if (nRet == SOCKET_ERROR) {
	          int WSAErr = WSAGetLastError();

  	          if (WSAErr != WSAEINTR) {
	            /* Display all errors except "operation interrupted"*/
	            WSAperror(WSAErr, "connect()", hInst);
                RemoveConn(lpstConn);
                lpstTask = 0L;
	            closesocket(hSock);
	            hSock = INVALID_SOCKET;
	          }
            }
          } else {
            /* Can't create a connection structure */
            closesocket(hSock);
            hSock = INVALID_SOCKET;
          }
        } else {
          /* Can't resolve destination port number */
          closesocket(hSock);
          hSock = INVALID_SOCKET;
        }
      } else {
        /* Can't resolve destination address */
        closesocket(hSock);
        hSock = INVALID_SOCKET;
      }
    }
    /* If we failed, we need to clean up */
    if (hSock == INVALID_SOCKET && lpstTask) {
      RemoveTask(lpstTask);
    }
  }
  return (hSock);
} /* end ConnectTCP() */

/*--------------------------------------------------------------
 * Function: SendData()
 *
 * Description: Send data amount requested from buffer passed
 */
int WINAPI SendData(SOCKET hSock, LPSTR lpOutBuf, int cbTotalToSend)
{
  LPCONNDATA lpstConn;
  int cbTotalSent = 0, cbSent;
  int nRet = SOCKET_ERROR;   /* assume error */
  
  lpstConn = FindConn(hSock, 0);
  if (!lpstConn) {
    /* Socket not found, so it's not valid */
    WSASetLastError(WSAENOTSOCK);
    
  } else {
    /* Subclass the window provided at connnect to filter message traffic */
    SetWindowLong (lpstConn->hwnd, GWL_WNDPROC, (DWORD)SubclassProc);
      
    while  (((cbTotalToSend - cbTotalSent) > 0) && 
	    (lpstConn->hSock != INVALID_SOCKET)) {
      cbSent = DoSend(hSock,
                      lpOutBuf+cbTotalSent,
                      cbTotalToSend - cbTotalSent,
                      lpstConn);
      if (cbSent != SOCKET_ERROR) {
        /* Tally and Quit the loop if we've sent amount requested */
        cbTotalSent += cbSent;
        if ((cbTotalToSend - cbTotalSent) <= 0)
          break;
      } else {
        /* If send failed, return an error */
        cbTotalSent = SOCKET_ERROR;
      }
    }
    /* Unsubclass active window before we leave */
    SetWindowLong(lpstConn->hwnd, GWL_WNDPROC, (long)lpstConn->lpfnWndProc);
  }
  return (cbTotalSent);
} /* end SendData() */

/*--------------------------------------------------------------
 * Function: DoSend()
 *
 * Description: Send data. We call this function from SendData(),
 *  or in response to FD_WRITE asynchronous notification.
 */
int DoSend(SOCKET hSock, LPSTR lpOutBuf, int cbTotalToSend, 
  LPCONNDATA lpstConn)
{
  int cbTotalSent  = 0;
  int cbLeftToSend = cbTotalToSend;
  int nRet, WSAErr;
  /* Send as much data as we can */
  while (cbLeftToSend > 0) {
  
    /* Send data to client */
    nRet = send (hSock, lpOutBuf+cbTotalSent, 
      cbLeftToSend < MTU_SIZE ? cbLeftToSend : MTU_SIZE, 0);

    if (nRet == SOCKET_ERROR) {
      WSAErr = WSAGetLastError();
      /* Display all errors except "operation interrupted" */
      if (WSAErr != WSAEINTR) {
        /*  unsubclass first so user can respond to error) */
        SetWindowLong(lpstConn->hwnd, GWL_WNDPROC,
	   (DWORD)lpstConn->lpfnWndProc);
        WSAperror(WSAErr, (LPSTR)"send()", hInst);
      }
      break;
    } else {
      /* Update byte counter, and display. */
      cbTotalSent += nRet;
    }
    /* calculate what's left to send */
    cbLeftToSend = cbTotalSent - cbTotalToSend; 
  }
  return (cbTotalSent);
} /* end DoSend() */

/*--------------------------------------------------------------
 * Function: RecvData()
 *
 * Description: Recieve data amount requested into buffer passed
 */
int WINAPI RecvData(SOCKET hSock, LPSTR lpInBuf, int cbTotalToRecv, int nTimeout)
{
  LPCONNDATA lpstConn;
  int cbTotalRcvd = 0, cbRcvd;
  int nRet = SOCKET_ERROR;   /* assume error */
  
  lpstConn = FindConn(hSock, 0);
  if (!lpstConn) {
    /* Socket not found, so it's not valid */
    WSASetLastError(WSAENOTSOCK);
    
  } else {
    /* Subclass the active window to filter message traffic */
    SetWindowLong (lpstConn->hwnd, GWL_WNDPROC, (DWORD)SubclassProc);
    
    /* Set a timer, if requested */
    if (nTimeout) {
      lpstConn->nTimeout = nTimeout;
      SetTimer(hWinMain, TIMEOUT_ID, nTimeout, 0L);
    }
      
    while  (((cbTotalToRecv - cbTotalRcvd) > 0) &&
	    (lpstConn->hSock != INVALID_SOCKET)) {
      cbRcvd = DoRecv(hSock,
                      lpInBuf+cbTotalRcvd,
                      cbTotalToRecv - cbTotalRcvd,
                      lpstConn);
      if (cbRcvd != SOCKET_ERROR) {
        /* Tally and Quit if we've received amount requested */
        cbTotalRcvd += cbRcvd;
        if ((cbTotalToRecv - cbTotalRcvd) <= 0) {
          if (lpstConn->nTimeout)

⌨️ 快捷键说明

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