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

📄 nonblkng.c

📁 windows 网络编程。pdf文档
💻 C
📖 第 1 页 / 共 3 页
字号:
/*--------------------------------------------------------------------------- 
 *  Program: WAL.EXE  WinSock Application Launcher
 *
 *  filename: nonblkng.c, 
 *
 *  copyright by Bob Quinn, 1995
 *
 *  Description:
 *   This module contains the Windows Sockets network code in a
 *   sample application that does non-blocking calls.
 *
 *  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>
#include <winsock.h> /* Windows Sockets */
#include <string.h>  /* for _fxxxxx() functions */ 

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

/*---------------------------------------------------------------------------
 * Function: nb_ds_cn()
 *
 * Description:
 *  Blocking datastream connect.
 *
 */
int nb_ds_cn (HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stLclAddr;	/* Socket structure */
	int	wRet = SOCKET_ERROR, i;		/* work variables */
	fd_set stWritFDS;	/* select() "file descriptor set" structures */
	fd_set stXcptFDS;
	struct timeval stTimeOut;	/* for select() timeout (none) */
	BOOL bInProgress = FALSE;
	u_long	lOnOff;
	int nWSAerror;

	/* Get a TCP socket (if we don't have one already) */
	if (stWSAppData.nSockState == STATE_NONE) {
		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);  

	/* make our socket non-blocking */
	lOnOff = TRUE;
	wRet = ioctlsocket(stWSAppData.nSock, FIONBIO, (u_long FAR *)&lOnOff);
	if (wRet) {	/* ioctlsocket() returns 0 on success */
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), (LPSTR)"ioctlsocket()", hInst);
		goto AppExit;
	}

	/* 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;
    /*----------------------------------------*/                                        

#if 0
/*------------------- Example of what NOT to do ---------------------------
 * This is one algorithm for detecting a TCP connection on a non-blocking
 *  socket that was used in BSD Sockets.  Don't do this!
 *
 * We don't connect() non-blocking this way because it is too dependent
 *  on specific error values to detect socket state.  It does not work
 *  because on Microsoft TCP/IP and others the second call to connect() 
 *  call gives WSAEINVAL instead of the expected (BSD-compatible) 
 *  WSAEALREADY.
 *  
 * The more robust and reliable way to detect the connection on a non-
 *  blocking socket--other than WSAAsyncSelect()--is to use select() 
 *  (which blocks).
 */
	i = 0;
	do {
		i++;
		wRet = connect(stWSAppData.nSock,
			(struct sockaddr FAR*)&stLclAddr,
			sizeof(struct sockaddr_in));

		/* on non-blocking connect, we expect errors:
		 *   - WSAEISCONN means success
		 *   - some mean retry
		 *   - some others are bad news
		 */
		if (wRet == SOCKET_ERROR) {
			nWSAerror = WSAGetLastError();
			if (nWSAerror == WSAEISCONN) {
				/* we're connected!! */
				break;
			
			} else if  ((nWSAerror == WSAEWOULDBLOCK) ||
						(nWSAerror == WSAEINPROGRESS) ||
						(nWSAerror == WSAEALREADY)) {
				/* need to retry */
				bInProgress = TRUE;
			} else {
				/* fatal error */
				wsprintf (achOutBuf, "connect(%d)", i);
	    		nb_close (hInst, hwnd);
				WSAperror(nWSAerror, achOutBuf, hInst);
				goto AppExit;
			}
		}		
	} while (bInProgress);
/*---------------------End of example what NOT to do---------------*/
#endif

	/*-------------------- begin using select() --------------------
	 * The proper (BSD-compatible) way to do a non-blocking connect()
	 *  in a loop does not work on many WinSocks (which return WSAEINVAL
	 *  on 2nd and subsequent connect() calls, instead of WSAEALREADY).
	 *
	 * Although using select() to detect connection completion is a
	 *  blocking call, it is the best method on a non-blocking socket.
	 *
	 * We'll allow a certain number of timeouts (e.g. select() returns
	 *  the value 0), then fail.
	 */
	 /* Now wait for "writability" to indicate connection completion, 
	  *  or an exception to indicate an error */
	 for (i= 0;;) {		/* we deal with counter inside the loop */
		wRet = connect(stWSAppData.nSock,
			(struct sockaddr FAR*)&stLclAddr,
			sizeof(struct sockaddr_in));

		/* on non-blocking connect, we expect WSAEWOULDBLOCK error 
		 *  but WSAEALREADY is ok too, and WSAEISCONN means we're 
		 *  done! 
		 */
		if (wRet == SOCKET_ERROR) {
			nWSAerror = WSAGetLastError();
			if (nWSAerror == WSAEISCONN) {
				/* we're connected!! */
				break;
			} else if  ((nWSAerror != WSAEWOULDBLOCK) &&
						(nWSAerror != WSAEALREADY)) {
				/* fatal error */
				wsprintf (achOutBuf, "connect(%d)", i);
	     		nb_close (hInst, hwnd);
				WSAperror(nWSAerror, achOutBuf, hInst);
				goto AppExit;
			}
		}		
		
 	    /* clear all sockets from FDS structure, then put our socket 
  	     *  into the socket descriptor set */
	    FD_ZERO((fd_set FAR*)&(stWritFDS));
	    FD_ZERO((fd_set FAR*)&(stXcptFDS));
#pragma	message ("--> WinSock FD_SET macro generates MSVC warning C4127 <--")
	    FD_SET(stWSAppData.nSock, (fd_set FAR*)&(stWritFDS));
	    FD_SET(stWSAppData.nSock, (fd_set FAR*)&(stXcptFDS));
	 
	 	/* initialize the timeout structure.  We use the same timeout as
	  	 *  our I/O polling loop.  However, we don't want to poll with
	  	 *  a zero timeout, since we don't have a blocking hook function
	  	 *  to yield we'll depend on WinSock's default blocking hook.
	  	 *  We use a nice round number for our timeout: 1 second. */
	 	stTimeOut.tv_sec  = CONN_TIMEOUT;
	 	stTimeOut.tv_usec = 0;
	 
	 	wRet = select(-1,				/* call select() */
	 		NULL,
	 		(fd_set FAR*)&(stWritFDS), 
	 		(fd_set FAR*)&(stXcptFDS), 
	 		(struct timeval FAR *)&(stTimeOut));
	 		
	 	if (wRet == SOCKET_ERROR) {		/* check return */
	 		/* all errors are bad news */
	    	nb_close (hInst, hwnd);
			WSAperror(WSAGetLastError(), "select()", hInst);
	 		goto AppExit;
	 		
	 	} else if (wRet > 0) {
	 		/* check for error (exception) first */
	 		if (FD_ISSET (stWSAppData.nSock,
	 			(fd_set FAR*)&(stXcptFDS))) {
	 			/* all errors are bad news */
	    		nb_close (hInst, hwnd);
				WSAperror(WSAGetLastError(),"select(excptn)", hInst);
	 			goto AppExit;
	 		}

	 		if (FD_ISSET (stWSAppData.nSock,(fd_set FAR*)&(stWritFDS))) {
	 			/* If "writable" socket set includes ours, we're connected! */
	 			break;
	 		} else {
	 			/* This should never happen!!!  If select returned
	 			 *  a positive value, something should be set in
	 			 *  either our exception or our read socket set  */
	 			MessageBox(hwnd,
	 				"Unexpected results from select()",
	 				"Error", MB_OK | MB_ICONHAND);
	 			nb_close(hwnd, hInst);
	 			goto AppExit;	/* bail! */
	 		} 
	 	} else {	/* wRet == 0 which indicates select() timeout */
	 		i++;	/* increment our timeout counter */
	 		if (i++ >= CONN_RETRIES) {
	 			/* if we've had our fill of retries, report error and exit */
	 			MessageBox(hwnd,
	 				"select() timeout exceeded",
	 				"Error", MB_OK | MB_ICONHAND);
	 			nb_close(hwnd, hInst);
	 			goto AppExit;
	 		}
	 	}
	 }
	/*-------------------- end using select() --------------------*/

	/*-------------------------------------*/
	stWSAppData.nSockState = STATE_CONNECTED;
	/*-------------------------------------*/
                            
    /* get timers for statistics updates & I/O (if requested) */                        
	get_timers(hInst, hwnd);
      
	/* Tell ourselves to do next step! */
	PostMessage(hwnd, WM_COMMAND, anIoCmd[stWSAppData.nIoMode], 0L);

AppExit:    
	return (wRet);

} /* end nb_ds_cn() */

/*---------------------------------------------------------------------------
 * Function: nb_ds_ls()
 *
 * Description:
 *  Blocking datastream listen/accept
 *
 */
int nb_ds_ls (HANDLE hInst, HANDLE hwnd)
{
	struct sockaddr_in stLclAddr;	/* Socket structures */
	struct sockaddr_in stRmtAddr;
	int	 nAddrLen;		/* for length of address structure */	
	u_long lOnOff;		/* on/off switch for ioctlsocket() command */
	SOCKET hNewSock;	/* new socket returned from accept() */
	fd_set stReadFDS;	/* select() "file descriptor set" structures */
	fd_set stXcptFDS;
	struct timeval stTimeOut;	/* for select() timeout (none) */
	int	wRet = SOCKET_ERROR;	/* work variables */
	int nWSAerror;

	/* Get a TCP socket (if we don't already have one) */
	if (stWSAppData.nSockState == STATE_NONE) {
		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);
	}

	/* make our socket non-blocking */
	lOnOff = TRUE;
	wRet = ioctlsocket(stWSAppData.nSock, FIONBIO, (u_long FAR *)&lOnOff);
	if (wRet) {	/* ioctlsocket() returns 0 on success */
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "ioctlsocket()", hInst);
		goto AppExit;
	}

	/* 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;
	/*---------------------------------*/

	/* Begin listening for incoming connections on socket */  
	wRet = listen(stWSAppData.nSock, 1);  
	if (wRet == SOCKET_ERROR) {
	    nb_close (hInst, hwnd);
		WSAperror(WSAGetLastError(), "listen()", hInst);

⌨️ 快捷键说明

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