📄 nonblkng.c
字号:
goto AppExit;
}
/*-------------------------------------*/
stWSAppData.nSockState = STATE_LISTENING;
/*-------------------------------------*/
do_stats(hwnd, hInst, FALSE); /* update window to show current state */
/*-------------------- begin using select() --------------------
* There is no good way to detect an incoming connection with
* a non-blocking socket (or non-blocking operation). Looping
* on accept() is possible (expecting WSAEWOULDBLOCK), but it
* incurs lots of CPU overhead.
*
* Since a non-blocking loop requires a blocking hook function
* anyway (to yield in Windows 3.x), we might as well use a
* blocking operation. Using the select() function to detect
* "readability" is the most common and acceptable way to do
* detect an incoming connection request (i.e. the "time to
* accept()" event).
*/
/* Now wait for "readability", or an error (exception) */
do {
/* clear all sockets from FDS structure, then put our socket
* into the socket descriptor set */
FD_ZERO((fd_set FAR*)&(stReadFDS));
FD_ZERO((fd_set FAR*)&(stXcptFDS));
#pragma message ("--> WinSock FD_SET macro generates MSVC warning C4127 <--")
FD_SET(stWSAppData.nSock, (fd_set FAR*)&(stReadFDS));
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 = 1;
stTimeOut.tv_usec = 0;
wRet = select(-1, /* call select() */
(fd_set FAR*)&(stReadFDS),
NULL,
(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*)&(stReadFDS)))) {
/* 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! */
}
}
} while (wRet == 0); /* 0 return means select() timeout expired */
/*-------------------- end using select() --------------------*/
/* 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);
/* Tell ourselves to do next step! */
PostMessage(hwnd, WM_COMMAND, anIoCmd[stWSAppData.nIoMode], 0L);
AppExit:
return (wRet);
} /* end nb_ds_ls() */
/*---------------------------------------------------------------------------
* Function: nb_dg_cn()
*
* Description:
* Blocking datagram "connect".
*
*/
int nb_dg_cn (HANDLE hInst, HANDLE hwnd)
{
struct sockaddr_in stLclAddr; /* Socket structure */
int wRet = SOCKET_ERROR; /* work variable */
u_long lOnOff;
/* Get a UDP socket */
if (stWSAppData.nSock) {
stWSAppData.nSock = socket (AF_INET, SOCK_DGRAM, 0);
if (stWSAppData.nSock == INVALID_SOCKET) {
WSAperror(WSAGetLastError(), "socket()", hInst);
goto AppExit;
}
}
/*---------------------------------*/
stWSAppData.nSockState = STATE_OPEN;
/*---------------------------------*/
/* 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;
}
/* 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;
/*----------------------------------------*/
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);
/* Tell ourselves to do next step! */
PostMessage(hwnd, WM_COMMAND, anIoCmd[stWSAppData.nIoMode], 0L);
AppExit:
return (wRet);
} /* end nb_dg_cn() */
/*---------------------------------------------------------------------------
* Function: nb_dg_ls()
*
* Description:
* Blocking datagram "listen".
*
*/
int nb_dg_ls (HANDLE hInst, HANDLE hwnd)
{
struct sockaddr_in stLclAddr; /* Socket structure */
int wRet = SOCKET_ERROR; /* work variable */
u_long lOnOff;
/* Get a UDP socket */
if (stWSAppData.nSockState == STATE_NONE) {
stWSAppData.nSock = socket (AF_INET, SOCK_DGRAM, 0);
if (stWSAppData.nSock == INVALID_SOCKET) {
WSAperror(WSAGetLastError(), "socket()", hInst);
goto AppExit;
}
/*---------------------------------*/
stWSAppData.nSockState = STATE_OPEN;
/*---------------------------------*/
}
/* 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; /* 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 */
/* Tell ourselves to do next step! */
PostMessage(hwnd, WM_COMMAND, anIoCmd[stWSAppData.nIoMode], 0L);
AppExit:
return (wRet);
} /* end nb_dg_ls */
/*---------------------------------------------------------------------------
* Function: nb_w_r()
*
* Description:
* Non-blocking write and read. Our CLIENTS connecting to ECHO port
* (by default) use this.
*/
int nb_w_r(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);
goto wr_end;
}
} else {
/* Tally amount sent, to see how much left to send */
cbOutLen += wRet;
stWSAppData.lBytesOut += wRet;
}
} /* end send() loop */
/* read as much as we can from the server, until we get an
* error, any error (most likely one is WSAEWOULDBLOCK
* which in effect means there's no more data to be read) */
for (;;) {
wRet = recv (stWSAppData.nSock, (LPSTR)achInBuf, BUF_SIZE, 0);
if (wRet == SOCKET_ERROR) {
nWSAerror = WSAGetLastError();
if (nWSAerror != WSAEWOULDBLOCK) {
nb_close (hInst, hwnd);
WSAperror(nWSAerror, "recv()", hInst);
goto wr_end; /* quit on error */
}
break; /* WouldBlock is not fatal */
} else if (wRet == 0) { /* Other side closed socket */
MessageBox (hwnd, achOutBuf,
"server closed connection", MB_OK);
do_close (hInst, hwnd, FALSE);
goto wr_end;
} else {
stWSAppData.lBytesIn += wRet;
}
} /* end recv() loop */
OurBlockingHook(); /* yield */
} /* end main loop */
wr_end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -