async.c

来自「windows 网络编程。pdf文档」· C语言 代码 · 共 685 行 · 第 1/2 页

C
685
字号
/*---------------------------------------------------------------------------
 *  Program: WAL.EXE  WinSock Application Launcher
 *
 *  filename: async.c
 *
 *  copyright by Bob Quinn, 1995
 *
 *  Description:
 *   This module contains the Windows Sockets network code in a
 *   sample application to uses asynchronous notification for I/O.
 *
 *  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. 
 *
 ----------------------------------------------------------------------------*/
#include <windows.h>
#include <windowsx.h> /* for 32-bit _fmemset */
#include <winsock.h>  /* Windows Sockets */
#include <string.h>   /* for _fxxxxx() functions */ 

#include "resource.h"
#include "..\winsockx.h"
#include "wal.h"


extern int recv_count;	/* number of recv() calls */
/*---------------------------------------------------------------------------
 * Function: as_ds_cn()
 *
 * Description:
 *  Asynch datastream connect.
 *
 */
int as_ds_cn (HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stLclAddr;	/* Socket structure */
	int	wRet = SOCKET_ERROR;		/* work variables */
	BOOL bInProgress = FALSE;
	int nWSAerror;

	/* Get a TCP socket */
	stWSAppData.nSock = socket (AF_INET, SOCK_STREAM, 0);
	if (stWSAppData.nSock == INVALID_SOCKET)  {
        WSAperror(WSAGetLastError(), "socket()", hInst);
        goto AppExit;
	}
    /*---------------------------------*/                                        
	stWSAppData.nSockState = STATE_OPEN;
    /*---------------------------------*/                                        

    /* Enable OOBInLine option if user asked to enable it */    
    if (stWSAppData.nOptions & OPTION_OOBINLINE) {
    		set_oobinline (hInst, hwnd, TRUE);
	}

	/* Initialize the Sockets Internet Address (sockaddr_in) structure */
	_fmemset ((LPSTR)&(stLclAddr), 0, sizeof(struct sockaddr_in)); 

	/* Get IP Address from a hostname (or addr string in dot-notation) */
	stLclAddr.sin_addr.s_addr = GetAddr(stWSAppData.szHost);

	/* register for asynchronous notification of all events
	 *  this socket could possibly get.(note: WSAAsyncSelect()
	 *  will also make the socket non-blocking) */
	wRet = WSAAsyncSelect(stWSAppData.nSock, hwnd, IDM_ASYNC,
		(FD_READ | FD_WRITE | FD_OOB | FD_CONNECT | FD_CLOSE));
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "WSAAsyncSelect()", hInst);
	}

	/* convert port number from host byte order to network byte order */
	stLclAddr.sin_port = htons (stWSAppData.nPortNumber);	
	stLclAddr.sin_family = PF_INET;	/* Internet Address Family */
    
    /*----------------------------------------*/                                        
	stWSAppData.nSockState = STATE_CONN_PENDING;
    /*----------------------------------------*/                                        

	wRet = connect(stWSAppData.nSock,
		(struct sockaddr FAR*)&stLclAddr, 
		sizeof(struct sockaddr_in));
	if (wRet == SOCKET_ERROR) {
		nWSAerror = WSAGetLastError();
		if (nWSAerror != WSAEWOULDBLOCK) {
	    	nb_close (hInst, hwnd);
			WSAperror(nWSAerror, "connect()", hInst);
			goto AppExit;
		}
	}
                            
    /* get timers for statistics updates & I/O (if requested) */                        
	get_timers(hInst, hwnd);

AppExit:    
	return (wRet);

} /* end as_ds_cn() */

/*---------------------------------------------------------------------------
 * Function: as_ds_ls()
 *
 * Description:
 *  Asynch datastream listen/accept for a TCP server
 *
 */
int as_ds_ls (HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stLclAddr;	/* Socket structures */
	int	wRet = SOCKET_ERROR;	/* work variables */

	/* Get a TCP socket */
	stWSAppData.nSock = socket (AF_INET, SOCK_STREAM, 0);
	if (stWSAppData.nSock == INVALID_SOCKET)  {
		WSAperror(WSAGetLastError(), "socket()", hInst);
		goto AppExit;
	}
	/*---------------------------------*/
	stWSAppData.nSockState = STATE_OPEN;
	/*---------------------------------*/

    /* Enable OOBInLine option if user asked to enable it */    
    if (stWSAppData.nOptions & OPTION_OOBINLINE) {
    		set_oobinline (hInst, hwnd, TRUE);
	}

	/* convert port number from host byte order to network byte order */
	stLclAddr.sin_port = htons (stWSAppData.nPortNumber);
	stLclAddr.sin_addr.s_addr = 0L;	/* no restriction on address */
	stLclAddr.sin_family = PF_INET;	/* Internet Address Family */

	/* Name the local socket */
	wRet = bind(stWSAppData.nSock,
		(struct sockaddr FAR*)&stLclAddr, 
		sizeof(struct sockaddr_in)); 
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "bind()", hInst);
		goto AppExit;
	}
	/*---------------------------------*/
	stWSAppData.nSockState = STATE_BOUND;
	/*---------------------------------*/

	/* register for asynchronous notification of all events
	 *  this socket could possibly get.(note: WSAAsyncSelect()
	 *  will also make the socket non-blocking) */
	wRet = WSAAsyncSelect(stWSAppData.nSock, hwnd, IDM_ASYNC,
		(FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE));
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(),"WSAAsyncSelect()", hInst);
	}

	/* Begin listening for incoming connections on socket */  
	wRet = listen(stWSAppData.nSock, 1);  
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "listen()", hInst);
		goto AppExit;
	}
	/*-------------------------------------*/
	stWSAppData.nSockState = STATE_LISTENING;
	/*-------------------------------------*/
	
	do_stats(hwnd, hInst, FALSE);	/* update window to show current state */
	
AppExit:    
	return (wRet);

} /* end as_ds_ls() */

/*---------------------------------------------------------------------------
 * Function: as_accept()
 *
 * Description:
 *   accept an incoming connection request (called after application
 *    receives an FD_ACCEPT asynchronous event notification message.
 */
int as_accept(HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stRmtAddr;
	SOCKET hNewSock;	/* new socket returned from accept() */
	int	 nAddrLen;		/* for length of address structure */	
	int nWSAerror;
	int wRet;
	
	/* Note: even though we expect accept() succeed immediately, it
	 *  could fail with "would block".  To protect, we loop on the
	 *  "would block" error.  Even in this simple loop with success
	 *  almost guaranteed, we need to have a blocking hook (yield) 
	 *  in this loop to keep from locking-up Windows 3.x. */
	do {                 
		/* Initialize the Sockets Internet Address (sockaddr_in) struct */
		_fmemset ((LPSTR)&(stRmtAddr), 0, sizeof(struct sockaddr_in));

		nAddrLen = sizeof(struct sockaddr_in);
		hNewSock = accept(stWSAppData.nSock,
			(struct sockaddr FAR*)&stRmtAddr, 
			(int FAR*)&nAddrLen); 
		if (hNewSock == INVALID_SOCKET) {
			nWSAerror = WSAGetLastError();
			if (nWSAerror != WSAEWOULDBLOCK) {
				/* anything but "would block" is bad news */
	    		nb_close (hInst, hwnd);
				WSAperror(nWSAerror, "accept()", hInst);
				wRet = SOCKET_ERROR;
				goto AppExit;
			}
		} else {
			break;	/* connection accepted! */
		}
		/* yield unto the non-operating system */
		OurBlockingHook();
		
	} while (nWSAerror == WSAEWOULDBLOCK);
	/*-------------------------------------*/
	stWSAppData.nSockState = STATE_CONNECTED;
	/*-------------------------------------*/
	
	/* This example is a (very) limited server that can only 
	 *  handle one connection at a time.  So, we close the 
	 * listening socket now and save the newly accepted one */
	wRet = nb_close (hInst, hwnd);	/* close listening socket */
	stWSAppData.nSock = hNewSock;	/* save new (accept) socket */

    /* get timers for statistics updates & I/O (if requested) */                        
	get_timers(hInst, hwnd);
	
AppExit:
	return (wRet);

} /* end as_accept() */

/*---------------------------------------------------------------------------
 * Function: as_dg_cn()
 *
 * Description:
 *  Asynch datagram "connect" for UDP clients
 *
 */
int as_dg_cn (HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stLclAddr;		/* Socket structure */
	int	 wRet = SOCKET_ERROR;		/* work variable */

	/* Get a UDP socket */
	stWSAppData.nSock = socket (AF_INET, SOCK_DGRAM, 0);
	if (stWSAppData.nSock == INVALID_SOCKET)  {
        WSAperror(WSAGetLastError(), "socket()", hInst);
        goto AppExit;
	}
	/*---------------------------------*/
	stWSAppData.nSockState = STATE_OPEN;
	/*---------------------------------*/

	/* Initialize the Sockets Internet Address (sockaddr_in) structure */
	_fmemset ((LPSTR)&(stLclAddr), 0, sizeof(struct sockaddr_in)); 

	/* Get IP Address from a hostname (or IP address string in dot-notation) */
	stLclAddr.sin_addr.s_addr = GetAddr(stWSAppData.szHost);

	/* convert port number from host byte order to network byte order */
	stLclAddr.sin_port = htons (stWSAppData.nPortNumber);	
	stLclAddr.sin_family = PF_INET;	/* Internet Address Family */
                                             
	/*----------------------------------------*/
	stWSAppData.nSockState = STATE_CONN_PENDING;
	/*----------------------------------------*/
                                               
	/* register for asynchronous notification of all events
	 *  this socket could possibly get.(note: WSAAsyncSelect()
	 *  will also make the socket non-blocking) */
	wRet = WSAAsyncSelect(stWSAppData.nSock, hwnd, IDM_ASYNC,
		(FD_READ | FD_WRITE));
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "WSAAsyncSelect()", hInst);
	}

	wRet = connect(stWSAppData.nSock,
		(struct sockaddr FAR*)&stLclAddr, 
		sizeof(struct sockaddr_in)); 
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "connect()", hInst);
		goto AppExit;
	}
      
	/*-------------------------------------*/
	stWSAppData.nSockState = STATE_CONNECTED;
	/*-------------------------------------*/

    /* get timers for statistics updates & I/O (if requested) */                        
	get_timers(hInst, hwnd);

AppExit:    
	return (wRet);

} /* end as_dg_cn() */

/*---------------------------------------------------------------------------
 * Function: as_dg_ls()
 *
 * Description:
 *  Asynch datagram "listen" for TCP servers.
 *
 */
int as_dg_ls (HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stLclAddr;		/* Socket structure */
	int	 wRet = SOCKET_ERROR;		/* work variable */

	/* Get a UDP socket */
	stWSAppData.nSock = socket (AF_INET, SOCK_DGRAM, 0);
	if (stWSAppData.nSock == INVALID_SOCKET)  {
		WSAperror(WSAGetLastError(), "socket()", hInst);
        goto AppExit;
	}
	/*---------------------------------*/
	stWSAppData.nSockState = STATE_OPEN;
	/*---------------------------------*/

⌨️ 快捷键说明

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