📄 nonblkng.c
字号:
/* Tell ourselves to do it again (if we're not
* using a timer and we're still connected)! */
if (!stWSAppData.nWinTimer &&
(stWSAppData.nSockState == STATE_CONNECTED))
PostMessage(hwnd, WM_COMMAND, IDM_WRITE_READ, 0L);
bBusyFlag = FALSE; /* reset semaphore */
return (cbOutLen);
} /* end nb_w_r() */
/*---------------------------------------------------------------------------
* Function: nb_r_w()
*
* Description:
* Blocking read and write. Our SERVERS providing ECHO service use this.
*/
int nb_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;
static int bBusyFlag = FALSE; /* semaphore */
if (bBusyFlag) /* use a semaphore to avoid being reentered */
return(0); /* when yielding (the nesting can be fatal) */
else
bBusyFlag = TRUE;
cbBufSize = stWSAppData.nLength; /* get the I/O size */
if (stWSAppData.nOptions & OPTION_SOUND)
MessageBeep(0xFFFF);
for (i=0; i<stWSAppData.nLoopLimit; i++, stWSAppData.wOffset++) {
/* 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, BUF_SIZE, 0);
if (wRet == SOCKET_ERROR) {
nWSAerror = WSAGetLastError();
if (nWSAerror != WSAEWOULDBLOCK) {
nb_close (hInst, hwnd);
WSAperror(nWSAerror,"send()", hInst);
goto rw_end;
}
/* exit recv() loop on WSAEWOULDBLOCK */
if (cbInLen == 0)
goto rw_end; /* 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_end;
} else {
cbInLen += wRet;
stWSAppData.lBytesIn += wRet;
}
} /* 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;
}
/* Tally amount sent, to see how much left to send */
cbOutLen += wRet;
stWSAppData.lBytesOut += wRet;
} /* end send() loop */
OurBlockingHook(); /* yield */
} /* 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 for statistics updates & I/O (if requested) */
get_timers(hInst, hwnd);
}
rw_end:
/* Tell ourselves to do it again (if we're not
* using a timer and we're still connected)! */
if (!stWSAppData.nWinTimer &&
(stWSAppData.nSockState == STATE_CONNECTED)) {
PostMessage(hwnd, WM_COMMAND, IDM_READ_WRITE, 0L);
}
bBusyFlag = FALSE; /* reset semaphore */
return (cbOutLen);
} /* end nb_r_w() */
/*---------------------------------------------------------------------------
* Function: nb_r()
*
* Description:
* Non-blocking read
*/
int nb_r(HANDLE hInst, HANDLE hwnd)
{
int cbInLen; /* Bytes in Input Buffer */
int cbBufSize; /* Length of I/O */
char achInBuf [BUF_SIZE]; /* Input Buffer */
int i, wRet, nWSAerror;
static int bBusyFlag = FALSE; /* semaphore */
if (bBusyFlag) /* use a semaphore to avoid being reentered */
return(0); /* when yielding (the nesting can be fatal) */
else
bBusyFlag = TRUE;
cbBufSize = stWSAppData.nLength;
if (stWSAppData.nOptions & OPTION_SOUND)
MessageBeep(0xFFFF);
for (cbInLen=0, i=0; i<stWSAppData.nLoopLimit; i++) {
/* read as much as we can from server */
wRet = recv (stWSAppData.nSock,
(LPSTR)achInBuf, BUF_SIZE, 0);
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 */
MessageBox (hwnd, achOutBuf,
"server closed connection", MB_OK);
do_close(hInst, hwnd, FALSE);
break;
} else {
/* tally amount received */
cbInLen += wRet;
/* 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);
}
}
OurBlockingHook(); /* yield */
} /* end main loop */
/* tally what we read */
stWSAppData.lBytesIn += cbInLen;
/* Tell ourselves to do it again (if we're not
* using a timer and we're still connected)! */
// if ((!stWSAppData.nWinTimer) &&
// (stWSAppData.nSockState == STATE_CONNECTED))
PostMessage(hwnd, WM_COMMAND, IDM_READ, 0L);
bBusyFlag = FALSE; /* reset semaphore */
return (cbInLen);
} /* end nb_r() */
/*---------------------------------------------------------------------------
* Function: nb_w()
*
* Description:
* Non-blocking write
*/
int nb_w(HANDLE hInst, HANDLE hwnd)
{
int cbOutLen=0; /* Bytes in Output Buffer */
int cbBufSize; /* Length of I/O */
int i, wRet, nWSAerror;
static int bBusyFlag = FALSE; /* semaphore */
if (bBusyFlag) /* use a semaphore to avoid being reentered */
return(0); /* when yielding (the nesting can be fatal) */
else
bBusyFlag = TRUE;
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 */
} else {
/* Tally amount sent */
cbOutLen += wRet;
stWSAppData.lBytesOut += wRet;
}
} /* end send() loop */
OurBlockingHook(); /* yield */
} /* end main loop */
/* Tell ourselves to do it again (if we're not
* using a timer and we're still connected)! */
if (!stWSAppData.nWinTimer &&
(stWSAppData.nSockState == STATE_CONNECTED))
PostMessage(hwnd, WM_COMMAND, IDM_WRITE, 0L);
bBusyFlag = FALSE; /* reset semaphore */
return (cbOutLen);
} /* end nb_w() */
/*---------------------------------------------------------------------------
* Function: nb_close()
*
* Description:
* Differences between this and a non-blocking close is that this cannot
* handle an WSAEWOULDBLOCK error gracefully (i.e. ignore it ), and this
* will* handle WSAEINPROGRESS gracefully.
*/
int nb_close (HANDLE hInst, HANDLE hwnd)
{
int wRet, nWSAerror; /* work variables */
/* we may have already set this state earlier,
* but not in all cases */
/*------------------------------------------*/
stWSAppData.nSockState = STATE_CLOSE_PENDING;
/*-----------------------------------------*/
/* Cancel any pending blocking operation */
if (WSAIsBlocking()) {
WSACancelBlockingCall();
}
/* Doing a close without calling shutdown(how=1), and looping on
* recv() first--the way we do in CloseConn() in our WinSockX.lib--
* is dangerous and not robust ...but we're experimenting here */
nWSAerror = 0;
wRet = closesocket(stWSAppData.nSock);
if (wRet == SOCKET_ERROR) {
nWSAerror = WSAGetLastError();
/* if not "would block" error, report it! */
if ((nWSAerror != WSAEWOULDBLOCK) && IsWindow(hwnd)) {
WSAperror(nWSAerror, "closesocket()", hInst);
}
}
/* Socket is invalid now (if it wasn't already) */
/*---------------------------------*/
stWSAppData.nSockState = STATE_NONE;
/*---------------------------------*/
/* free the timer resource(s) (if window not destroyed yet) */
if (IsWindow (hwnd)) {
KillTimer (hwnd, STATS_TIMER_ID);
if (stWSAppData.nWinTimer)
KillTimer (hwnd, APP_TIMER_ID);
}
return (wRet);
} /* end nb_close() */
/*---------------------------------------------------------------------------
* Function: OurBlockingHook()
*
* Description:
*/
void OurBlockingHook () {
BOOL bRet;
MSG msg;
int i;
/* loop on messages, but don't loop forever */
for (i = 0; i < DFLT_LOOP_MAX; i++) {
bRet = (BOOL)PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if (bRet) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
break; /* leave, if nothing to do */
}
}
return;
} /* end OurBlockingHook() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -