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

📄 wal.c

📁 windows 网络编程。pdf文档
💻 C
📖 第 1 页 / 共 5 页
字号:

	EndPaint(hwnd, &ps);
} /* end do_stats */

/*----------------------------------------------------------------------
 *
 * Function: get_timers()
 *
 * Description: We get one timer for statistic updates, and *another*
 *   timer if the user elects to launch a timer-driven application.
 *
 *  NOTE: We sometimes use *two* timers here.  Considering timers are a 
 *   limited resource, and especially since we could design it to use
 *   only one timer efficiently, this is not good.  I'm being lazy
 *   here, plain and simple, but then again the timer-driven app is
 *   not recommended anyway (it's just for experimentation).
 */
void get_timers (HANDLE hInst, HANDLE hwnd)
{
    hInst = hInst;	/* avoid warning */
    
	/* Set timer for statistics updates (every second) */
	if (!SetTimer (hwnd, STATS_TIMER_ID, STATS_INTERVAL, NULL)) {
		MessageBox (hwnd, 
			"Can't Get Windows Timer (for stats)", 
			"Error", MB_ICONEXCLAMATION | MB_OK);
	} else {
		KillTimer(hwnd, APP_TIMER_ID);
		 
		if (stWSAppData.nWinTimer) {
			/* Get timer if user wants timer-driven application */
			if (!SetTimer (hwnd, APP_TIMER_ID, 
				stWSAppData.nWinTimer, NULL)) {
				MessageBox (hwnd, 
					"Can't Get Windows Timer (for app)", "Error", 
					MB_ICONEXCLAMATION | MB_OK);
			}
		}
	}
	
	do_stats (hwnd, hInst, TRUE);	/* update stats display */
	
} /* end get_timers() */
                        
                        
/*----------------------------------------------------------------------
 * Function: SetNewTimer()
 *
 * Description: Set a new timeout period for our timer.
 */
void SetNewTimer (HANDLE hwnd, int nOldTimer, int nNewTimer)
{
	/* If we had a timer before, kill it (yea, this is unnecessary
	 *  since SetTimer() automatically kills the old timer, but
	 *  I *like* being paranoid). */
	if (nOldTimer)
		KillTimer (hwnd, APP_TIMER_ID);
		    				
	/* If we have a timer now, set it */
	if (nNewTimer) {
		if (!SetTimer (hwnd, APP_TIMER_ID, nNewTimer, NULL)) {
				MessageBox (hwnd, "Can't Get Windows Timer (for app)", 
					"Error", MB_ICONEXCLAMATION | MB_OK);
		}
	}
} /* end SetNewTimer() */

/*----------------------------------------------------------------------
 *
 * Function: LoopTimer()
 *
 * Description: Loop for a time-period, rather than waiting for reciept
 *  of a timer message (which is often unreliable on a busy system).
 */
void LoopTimer (BOOL IOStartFlag)
{
	static u_long lLastTicks;		/* Tick Count after last I/O */
	u_long lTicksSince;
	
	if (IOStartFlag)						/*** if ENTERING I/O loop */ 
	{
		lTicksSince = (GetTickCount() - lLastTicks);
		if (!lTicksSince) {  	/* if no time passed since last call */
			stWSAppData.nLoopsDn++;
			stWSAppData.nLoopsUp = 0;
			if (stWSAppData.nLoopsDn >= stWSAppData.nLoopsDnMax) {
				stWSAppData.nLoopsDn = 0;
				
				/* Decrease the number of loops per IO call, if possible */
				if (stWSAppData.nLoopLimit > 1)
					stWSAppData.nLoopLimit -= 1;
			}
		} else {
			stWSAppData.nLoopsUp++;
			stWSAppData.nLoopsDn = 0;
			if (stWSAppData.nLoopsUp >= stWSAppData.nLoopsUpMax) {
				stWSAppData.nLoopsUp = 0;
				
				/* Increment the number of loops per IO call, if it's
				 *  still less than the maximum value user set */
				if (stWSAppData.nLoopLimit < stWSAppData.nLoopMax)
					stWSAppData.nLoopLimit += 1;
			}
		}
		/* Increment the counter for the (calling) I/O function */
		stWSAppData.lCallCount++; 
	} 
	else									/*** if EXITING I/O loop ***/ 
	{
		/* Get Tick Count to see how soon we re-enter */
		lLastTicks = GetTickCount();
	}		
	return;
}	/* end LoopTimer() */

/*----------------------------------------------------------------------
 * Function: do_close()
 *
 * Description: Depending on the current socket state and the operation
 *  mode, we either initiate a close or complete a close.
 */
int do_close (HANDLE hInst, HANDLE hwnd, LPARAM bExitFlag)
{
	int wRet;
	int nOldState;
	
	wRet = IDOK;
	nOldState = stWSAppData.nSockState;
	
	if (nOldState == STATE_CONNECTED) {		/* connected? */
					
		/* it's premature to reset socket state here, 
		 *  but we do it to expedite the socket close */
		/*-----------------------------------------*/
		stWSAppData.nSockState = STATE_CLOSE_PENDING;
		/*-----------------------------------------*/
						
		/*---------------------------------------------------------------------*/
		/* NOTE: could add a dialog box here, to get closesocket timeout value */
		/*---------------------------------------------------------------------*/
		if (stWSAppData.nProtocol == PROT_DS) {	/* if it's a datastream socket */
		     wRet = MessageBox (				/*  ask if close gracefully */
				hwnd,                           /*  and set timeout = 0 if not */
	   			"Close Connection Gracefully?",
				"Close",
	    		MB_ICONQUESTION | MB_YESNOCANCEL); 

#if 0
            /*------NOTE: This method of blocking close DOES NOT WORK-------*/
            /* Check for and cancel pending blocking operation before we proceed! */
		   	if ((wRet != IDCANCEL) &&
		   		(WSAIsBlocking()))  {
		   		
		   		/* Cancel the blocking call */
		   		WSACancelBlockingCall();
		   		
		   		/* Now wait until the cancelled function returns (should
		   		 *  fail with WSAEINTR error), before we close the socket */
		   		do {
		   			OurBlockingHook();
		   		} while (WSAIsBlocking());
			} 
	    /*------------------ end of BAD example -----------------------*/
#endif	    	

	    	if (wRet == IDOK) {
				/* Connection abort requested, need to set
	 			 *  close timeout ("linger" value) to 0.
		 		 */
				struct linger stLinger;
				int WSAerr;
		
		   		stLinger.l_onoff = 1;   /* Linger On */
		   		stLinger.l_linger = 0;  /* 0 Seconds */
		   				
   				if (setsockopt(stWSAppData.nSock,
	           			SOL_SOCKET,
		   				SO_LINGER,
		   				(char FAR*) &stLinger,
		   				sizeof(struct linger))) {
		   			WSAerr = WSAGetLastError();
   					if (WSAerr == WSAEINPROGRESS) {
   						bl_close(hInst, hwnd);
   					} else {
        				WSAperror(WSAerr, "setsockopt()", hInst);
        			}
        		}
	    	}
	    } else {		/* if not Datastream, then it's Datagram */
	   		wRet = MessageBox (		/* ask if they're sure they want to close */
	    		hwnd,
	    		"Are you sure you want to close the socket?",
	    		"Close",
	    		MB_ICONQUESTION | MB_OKCANCEL);
	    }
	}  /* end if STATE_CONNECTED */
	    			 
	/*
	 * If we have a socket and operation is not cancelled, then close the socket
	 */
	if (stWSAppData.nSockState > STATE_NONE) {
	    if (wRet != IDCANCEL) {
			switch (stWSAppData.nOpMode) {
				case OPMODE_BL: 
					wRet = bl_close (hInst, hwnd);
					break;                          
				case OPMODE_NB:
				case OPMODE_AS:
					wRet = nb_close (hInst, hwnd);
					break;                          
			}
		} else {
			/* cancel close requested */
			stWSAppData.nSockState = nOldState;		/* reset state */
			if (nOldState == STATE_CONNECTED)		/* if it was connected, jumpstart */
				PostMessage(hwnd, WM_COMMAND, anIoCmd[stWSAppData.nIoMode], 0L);
			return TRUE;
		}	
	} else if (!bExitFlag) {
		MessageBox (hwnd, "No Sockets Open", "Can't Close", MB_OK | MB_ICONINFORMATION);
	}
	return FALSE;
} /* end do_close() */

/*--------------------------------------------------------------------
 * Function: WALWndProc()
 *
 * Description: Main window procedure
 */
LONG CALLBACK WALWndProc
	(HWND hwnd,
	 UINT msg,
	 WPARAM wParam,
	 LPARAM lParam)
{
    static HANDLE hInst;
    FARPROC lpfnWSAppDlgProc, lpfnWSOptionProc;
    int wRet, nFDError, nMsgQSize, i, j;
    HMENU hWalMenu;
    
    if (!stWSAppData.lBytesOut && !stWSAppData.lBytesIn)
    	stWSAppData.lStartTime = GetTickCount();	/* Start Time */
	                             
    switch (msg) {
   		case IDM_ASYNC:
   			/*----------------------------------------------
   			 * WSAAsyncSelect() event notification messages 
   			 *---------------------------------------------*/
   			nFDError = WSAGETSELECTERROR(lParam);		/* check async error */
   			if (nFDError) {
   				int nFDEvent = WSAGETSELECTEVENT(lParam);
   				
   				/* close the socket */
   				nb_close (hInst, hwnd);
   				
				/* if socket is active, notify user of error this asynch event message had */     
				if (!(stWSAppData.nSockState & (STATE_NONE | STATE_CLOSE_PENDING))) {
                    for (i=0, j=nFDEvent; j; i++, j>>=1); /* convert bit to index */
   					WSAperror(nFDError, aszWSAEvent[i], hInst);
   			    }
   			}
			switch (WSAGETSELECTEVENT(lParam)) {	/* check async event */
				case FD_OOB:
                     MessageBeep (MB_ICONASTERISK);
					 nb_oob_rcv (hInst, hwnd);
					 break;
				case FD_READ:
					/* we do multiple recv() calls per each FD_READ message we process,
					 *  so we keep count of the number and ignore that many FD_READ
					 *  messages.  The threshold is at 2 since 1 recv() is legitimate,
					 *  and the other may not have had data (if it failed with an
					 *  WSAEWOULDBLOCK error */
					if (recv_count > 2) {
						recv_count--;
						break;
					}

					/* rather than post the I/O message, we call the appropriate function to 
					 *  avoid the overhead involved with posting a message to proceed */
					 if (!(stWSAppData.nSockState  & (STATE_CONNECTED | STATE_BOUND))) {
					 	/* This message must have been left over 
					 	 *  in our message queue after a close */
					 	break;
					 }
					 switch (stWSAppData.nIoMode) {
					 	case IOMODE_R:
			 			case IOMODE_WR:
			 				/* do the read with more possible loops, to accomodate the
			 				 *  asynchronous nature and "bunching" of incoming packets */
			 				as_r (hInst, hwnd, (stWSAppData.nLoopLimit << 1));
			 				break;
			 			case IOMODE_RW:
			 				as_r_w (hInst, hwnd);
			 				break;
			 			case IOMODE_W:
			 				/* we shouldn't see the FD_READ event, so ask user what to do */
			 				wRet = MessageBox(hwnd, 
			 					"Data received, but application is write-only.  Read it?",
			 					"Unexpected Condition",
			 					MB_YESNO | MB_ICONQUESTION);
			 				if (wRet == IDYES)
			 					as_r (hInst, hwnd, DFLT_LOOP_MAX);
			 				break;
			 			}
					break;
				case FD_WRITE:
					/* Either we've just connected, so we're starting I/O for the first
					 *  time, or we've just got some outgoing buffers after a send()
					 *  failed with WSAEWOULDBLOCK so we should be able to send again. */
					 if (!(stWSAppData.nSockState  & (STATE_CONNECTED | STATE_BOUND))) {
					 	/* This message must have been left over 
					 	 *  in our message queue after a close */
					 	break;
					 }
					 switch (stWSAppData.nIoMode) {
					 	case IOMODE_R:
			 				/* nothing to do here since the application is read-only 
			 				 *  (its not sending any data).  We really shouldn't have 
			 				 *  registered for the FD_WRITE event, since our application
			 				 *  didn't need it.*/
			 				break;
			 			case IOMODE_WR:
			 			    /* write chargen data (printable ASCII character sequence 
			 			     *  we generate) */
			 				as_w_r (hInst, hwnd);
			 				break;
			 			case IOMODE_RW:
			 				/* we only have something to do for our "read then write" 
			 				 *  (server) application if we're recovering from a send()
			 				 *  that failed with a WSAEWOULDBLOCK error.  In that case
			 				 *  we should have a count of bytes left to write (where
			 				 *  we left off when our write failed). */
			 				if (stWSAppData.nOutLen) {
			 					as_r_w (hInst, hwnd);
			 				}
			 				break;
			 			case IOMODE_W:
			 				/* echo data that we received (the stWSAppData.nBytesToSend)*/
			 				as_w (hInst, hwnd);
			 				break;
			 		}
					break;
				case FD_ACCEPT:
					/* we have a connection request pending, accept it and start I/O */
					as_accept(hInst, hwnd);
					break;
				case FD_CONNECT:
					/* Set the socket state (if no error), and 
					 *  we'll start I/O with FD_WRITE */
					if (!nFDError) {
						/*-------------------------------------*/
						stWSAppData.nSockState = STATE_CONNECTED; 
						/*-------------------------------------*/
					} else {
						/* close the socket, if there's an error */
						do_close(hInst, hwnd, FALSE);
					}
					break;
				case FD_CLOSE:
					/* BQ NOTE: I just realized, I'd rather have my close functions call
					 *  shutdown(), recv() (or ioctlsocket(FIONREAD) if blocking socket), 
					 *  then call closesocket().
					 */
					if (stWSAppData.nSockState == STATE_CONNECTED)
						nb_close(hInst, hwnd);
			}
			break;

        case WM_COMMAND:
	    	switch (wParam) {
				case IDM_WRITE_READ:
					switch (stWSAppData.nOpMode) {
						case OPMODE_BL: 
							bl_w_r (hInst, hwnd);
							break;
						case OPMODE_NB:
							nb_w_r (hInst, hwnd);
							break;
						case OPMODE_AS:

⌨️ 快捷键说明

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