async.c

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

C
685
字号
	/* 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);
	}

	/* convert port number from host byte order to network byte order */
	stLclAddr.sin_port = htons (stWSAppData.nPortNumber);	
	stLclAddr.sin_addr.s_addr = 0L;	/* don't restrict incoming address */
	stLclAddr.sin_family = PF_INET;	/* Internet Address Family */
                                              
	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;
	/*---------------------------------*/

	do_stats(hwnd, hInst, FALSE);	/* update window to show current state */

AppExit:    
	return (wRet);

} /* end as_dg_ls */


/*---------------------------------------------------------------------------
 * Function: as_w_r()
 *
 * Description:
 *   Asynch write and read.  Our CLIENTS connecting to ECHO port use this.
 */
int as_w_r(HANDLE hInst, HANDLE hwnd)
{
	int	cbOutLen=0;               /* Bytes in Output Buffer */
	int	cbBufSize;				/* Length of I/O */
	int	nLoopLimit;
	int	i,wRet=0,nWSAerror;
	
	cbBufSize = stWSAppData.nLength;
	
	/* sound beep if I/O sound enabled */
	if (stWSAppData.nOptions & OPTION_SOUND)
			MessageBeep(0xFFFF);
			
	/* Adjust the loops per I/O call */
	LoopTimer(TRUE);
		
	/* Read as much as we can first */
	as_r(hInst, hwnd, DFLT_LOOP_MAX);

	nLoopLimit = stWSAppData.nLoopsLeft ? 
		stWSAppData.nLoopsLeft : stWSAppData.nLoopLimit;
	for (i=0; i<nLoopLimit; i++, stWSAppData.wOffset++) {

	    /* adjust offset into output string buffer */
	    if (stWSAppData.wOffset >= cbBufSize) {
	    	stWSAppData.wOffset = 0;
	    }
	     
	    cbOutLen = stWSAppData.nOutLen;	/* pick-up where we left off */
		stWSAppData.nOutLen = 0;		/* reset marker */

	    /* write to server */
	    while (cbOutLen < cbBufSize) {
		    wRet = send (stWSAppData.nSock, 
		    	(LPSTR)&(achChargenBuf[stWSAppData.wOffset+cbOutLen]),
		    	(cbBufSize-cbOutLen), 0);
		    if (wRet == SOCKET_ERROR) {
		    	nWSAerror = WSAGetLastError();
		    	if (nWSAerror != WSAEWOULDBLOCK) {
	    			nb_close (hInst, hwnd);
        			WSAperror(nWSAerror, "send()", hInst);
        		} 

        		/* Keep a marker, so we can pick-up where we leave off */
        		stWSAppData.nOutLen = cbOutLen;
        		stWSAppData.nLoopsLeft = nLoopLimit - i;
        		
			    goto wr_end; /* exit on any error 
			    			 (including WSAEWOULDBLOCK) */
		    } else {
				/* Tally amount sent, to see how much left to send */
		    	cbOutLen += wRet;
		    	stWSAppData.lBytesOut += wRet;
		    	
		    	/* stop if we've reached our limit */
		    	if (stWSAppData.nBytesMax &&
		    		(stWSAppData.lBytesOut >= stWSAppData.nBytesMax)) {
		    			do_close(hInst, hwnd, FALSE);
		    			goto wr_end;
		    	}
		    }     
	    } /* end send() loop */
	} /* end main loop */

	/* Send OOB Data if we want to */
	if (stWSAppData.nOptions & OPTION_OOBSEND) {
		nb_oob_snd (hInst, hwnd);
	}
	
	/* init to normal value (we completed all iterations) */
	stWSAppData.nLoopsLeft = stWSAppData.nLoopLimit;
	
wr_end:
	LoopTimer(FALSE);	/* set exit time from I/O loop */

	return (cbOutLen); 
	
} /* end as_w_r() */

/*---------------------------------------------------------------------------
 * Function: as_r_w()
 *
 * Description:
 *  Asynch read and write.  Our SERVERS providing ECHO service use this.
 */
int as_r_w(HANDLE hInst, HANDLE hwnd)
{
	int		cbInLen;                /* Bytes in Input Buffer */
	int		cbOutLen=0;             /* Bytes in Output Buffer */
	int		cbBufSize;				/* Length of I/O */
	int		i, wRet, nWSAerror;
                                                       
	cbBufSize = stWSAppData.nLength;
	
	if (stWSAppData.nOptions & OPTION_SOUND)
		MessageBeep(0xFFFF);
		
	for (i=0, recv_count=0; i<stWSAppData.nLoopLimit; i++) {
	     
	    /* read as much as we can from client (no less than I/O length
	     *  user requested, but more than that is ok) */
	    cbInLen = 0;
	    while (cbInLen < cbBufSize) {
		    wRet = recv (stWSAppData.nSock, 
			    (LPSTR)&(achInBuf[cbInLen]), BUF_SIZE-cbInLen, 0);
			recv_count++;	/* count recv() calls */
		    if (wRet == SOCKET_ERROR) {
		    	nWSAerror = WSAGetLastError();
		    	if (nWSAerror != WSAEWOULDBLOCK) {
	    			nb_close (hInst, hwnd);
        			WSAperror(nWSAerror, "send()", hInst);
			    	goto rw_exit;
        		}
        		/* exit recv() loop on WSAEWOULDBLOCK */
        		if (cbInLen == 0)
        			goto rw_exit;	/* quit if nothing read yet */
        		else
	        		break;			/* else write out what we read */
        		
		    } else if (wRet == 0) { /* Other side closed socket */
    			MessageBox (hwnd, achOutBuf, 
					"client closed connection", MB_OK);
				do_close (hInst, hwnd, FALSE);
				goto rw_exit;
		    } else {
		    	cbInLen += wRet;
		    	stWSAppData.lBytesIn += wRet;
		    	
		    	/* stop if we've reached our limit */
		    	if (stWSAppData.nBytesMax &&
		    		(stWSAppData.lBytesIn >= stWSAppData.nBytesMax)) {
		    			do_close(hInst, hwnd, FALSE);
		    			break;
		    	}
		    }
        } /* end recv() loop */ 
        
	    /* write to client, as much as we just read */
	    cbOutLen = 0;
	    while (cbOutLen < cbInLen) {
		    wRet = send (stWSAppData.nSock, 
		    	(LPSTR)&(achInBuf[cbOutLen]), 
		    	(cbInLen-cbOutLen), 0);
		    if (wRet == SOCKET_ERROR) {
		    	nWSAerror = WSAGetLastError();
		    	if (nWSAerror != WSAEWOULDBLOCK) {
				    nb_close (hInst, hwnd);
        			WSAperror(nWSAerror, "send()", hInst);
			    	goto rw_end;
        		}
        		break;
		    } else if (wRet == 0) {
		    	/* not likely, but possible */
		    	break;
		    }
			/* Tally amount sent, to see how much left to send */
		    cbOutLen += wRet;
		    stWSAppData.lBytesOut += wRet;
	    } /* end send() loop */
	} /* end main loop */
rw_end:   
	/* Datagram Servers aren't "connected" until data arrives, 
	 *  so change it now (and start timer) */
	if ((stWSAppData.nSockState < STATE_CONNECTED) &&
		(stWSAppData.nSockState > STATE_NONE)) {
	
		/*--------------------------------------*/
	    stWSAppData.nSockState = STATE_CONNECTED;
		/*--------------------------------------*/
		
		/* get timers for statistics updates & I/O (if requested) */
		get_timers(hInst, hwnd);
	}
rw_exit:		
	return (cbOutLen); 
} /* end as_r_w() */

/*---------------------------------------------------------------------------
 * Function: as_r()
 *
 * Description:
 *   Asynch read
 */
int as_r(HANDLE hInst, HANDLE hwnd, int nLoopLimit)
{
	int		cbInLen;
	int		i, wRet, nWSAerror;
                                                       
	if (stWSAppData.nOptions & OPTION_SOUND)
		MessageBeep(0xFFFF);
		
	for (cbInLen=0, recv_count=0, i=0; i<nLoopLimit; i++) {
         
	    /* read as much as we can from server (no less than I/O length
	     *  user requested, but more than that is ok) */
	    wRet = recv (stWSAppData.nSock, 
		    (LPSTR)achInBuf, BUF_SIZE, 0);
		recv_count++;	/* count recv() calls */
	    if (wRet == SOCKET_ERROR) {
	    	nWSAerror = WSAGetLastError();
	    	if (nWSAerror != WSAEWOULDBLOCK) {
			    nb_close (hInst, hwnd);
       			WSAperror(nWSAerror, "send()", hInst);
       		}
		    break;	/* break on any error (including WSAEWOULDBLOCK) */
	    } else if (wRet == 0) { /* Other side closed socket */
    		/* if we're connected, tell user and close */
  			MessageBox (hwnd, achOutBuf, 
				"server closed connection", MB_OK);
			do_close(hInst, hwnd, FALSE);
			break;
	    } else {
		    /* tally amount received */
		    cbInLen += wRet;
			stWSAppData.lBytesIn += wRet;
		    
		    /* stop if we've reached our limit */
		    if (stWSAppData.nBytesMax &&
		    	(stWSAppData.lBytesIn >= stWSAppData.nBytesMax)) {
		    		do_close (hInst, hwnd, FALSE);
		    		break;
		    }
	    }
	} /* end main loop */
	
	/* Datagram Servers aren't "connected" until data arrives, 
	 *  so change it now (and start timer) */
	if ((stWSAppData.nSockState < STATE_CONNECTED) &&
		(stWSAppData.nSockState > STATE_NONE)) {

    	/*--------------------------------------*/
	    stWSAppData.nSockState = STATE_CONNECTED;
		/*--------------------------------------*/
	    
	    get_timers(hwnd, hInst);
	}
	
	return (cbInLen);
} /* end as_r() */

/*---------------------------------------------------------------------------
 * Function: as_w()
 *
 * Description:
 *   Asynch write
 */
int as_w(HANDLE hInst, HANDLE hwnd)
{
	int		cbOutLen=0;             /* Bytes in Output Buffer */
	int		cbBufSize;				/* Length of I/O */
	int		i, wRet, nWSAerror;
                                                       
	cbBufSize = stWSAppData.nLength;
	
	if (stWSAppData.nOptions & OPTION_SOUND)
		MessageBeep(0xFFFF);
		
	for (i=0; i<stWSAppData.nLoopLimit; i++, stWSAppData.wOffset++) {

		/* adjust offset into output string buffer */
		if (stWSAppData.wOffset >= cbBufSize) {  
			stWSAppData.wOffset = 0;
		}
	     
		/* write to server */
		cbOutLen = 0;
		while (cbOutLen < cbBufSize) {
		    wRet = send (stWSAppData.nSock, 
		    	(LPSTR)&(achChargenBuf[stWSAppData.wOffset+cbOutLen]),
		    	(cbBufSize-cbOutLen), 0);
		    if (wRet == SOCKET_ERROR) {
		    	nWSAerror = WSAGetLastError();
		    	if (nWSAerror != WSAEWOULDBLOCK) {
	    			nb_close (hInst, hwnd);
        			WSAperror(nWSAerror, "send()", hInst);
        		}
			    break;	/* break on any error.  If WSAEWOULDBLOCK,
			             *  then FD_WRITE will restart sending */
		    } else {
			    /* Tally amount sent */
			    cbOutLen += wRet;
			    stWSAppData.lBytesOut += wRet;
		    
		    	/* stop if we've reached our limit */
		    	if (stWSAppData.nBytesMax &&
		    		(stWSAppData.lBytesOut >= stWSAppData.nBytesMax)) {
		    			do_close (hInst, hwnd, FALSE);
		    			break;
		    	}
		    }
	    } /* end send() loop */
	} /* end main loop */
	
	/* Send OOB Data if we want to */
	if (stWSAppData.nOptions & OPTION_OOBSEND) {
		nb_oob_snd (hInst, hwnd);
	}

	return (cbOutLen); 
} /* end as_w() */

⌨️ 快捷键说明

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