📄 wsasimpl.c
字号:
/* Release timer, if there is one */
KillTimer (lpstConn->hwnd, TIMEOUT_ID);
break;
}
if (lpstConn->nTimeout) {
/* Reset timer, if there is one */
SetTimer(hWinMain, TIMEOUT_ID, lpstConn->nTimeout, 0L);
}
} else {
/* If receive failed, return an error */
cbTotalRcvd = SOCKET_ERROR;
}
}
/* Unsubclass active window before we leave */
SetWindowLong(lpstConn->hwnd, GWL_WNDPROC, (long)lpstConn->lpfnWndProc);
lpstConn->nTimeout = 0; /* reset timer */
}
return (cbTotalRcvd);
} /* end RecvData() */
/*--------------------------------------------------------------
* Function: DoRecv()
*
* Description: Receive data into buffer. We call this function
* in response to FD_READ asynchronous notification.
*/
int DoRecv(SOCKET hSock, LPSTR lpInBuf, int cbTotalToRecv,
LPCONNDATA lpstConn)
{
int cbTotalRcvd = 0;
int cbLeftToRecv = cbTotalToRecv;
int nRet=0, WSAErr;
/* Read as much as we can buffer from client */
while (cbLeftToRecv > 0) {
nRet = recv (hSock,lpInBuf+cbTotalRcvd, cbLeftToRecv, 0);
if (nRet == SOCKET_ERROR) {
WSAErr = WSAGetLastError();
/* Display all errors except "operation interrupted" */
if (WSAErr != WSAEINTR) {
WSAperror(WSAErr, (LPSTR)"recv()", hInst);
/* unsubclass first so user can respond to error) */
SetWindowLong(lpstConn->hwnd,GWL_WNDPROC,
(DWORD)lpstConn->lpfnWndProc);
}
break;
} else if (nRet == 0) { /* Other side closed socket */
/* quit if server closed connection */
break;
} else {
/* Update byte counter */
cbTotalRcvd += nRet;
}
cbLeftToRecv = cbTotalToRecv - cbTotalRcvd;
}
return (cbTotalRcvd);
} /* end DoRecv() */
/*--------------------------------------------------------------
* Function: CloseTCP()
*
* Description: Do a graceful close of a TCP connection using
* the robust algorithm of "half-closing" with shutdown(how=1),
* then loop on recv() to read remaining data until it fails,
* or returns a zero, then call closesocket().
*/
int WINAPI CloseTCP(SOCKET hSock, LPSTR lpInBuf, int len)
{
int nRet = SOCKET_ERROR, cbBytesDone=0;
LPCONNDATA lpstConn;
lpstConn = FindConn(hSock, 0);
if (!lpstConn) {
/* Socket not found, so it's not valid */
WSASetLastError(WSAENOTSOCK);
} else {
if (WSAIsBlocking()) {
/* Can't close socket now since blocking operation pending,
* so just cancel the blocking operation and we'll close
* connection when pending operation fails with WSAEINTR */
WSACancelBlockingCall();
} else {
/* Signal the end is near */
lpstConn->hSock = INVALID_SOCKET;
/* Half-close the connection to close neatly (we ignore the error here
* since some WinSocks fail with WSAEINVAL if they've recieved a RESET
* on the socket before the call to shutdown(). */
nRet = shutdown (hSock, 1);
/* Read and discard remaining data (until EOF or any error) */
nRet = 1;
while (nRet && (nRet != SOCKET_ERROR)) {
nRet = recv (hSock, lpInBuf, len-cbBytesDone, 0);
if (nRet > 0)
cbBytesDone += nRet;
}
/* close the socket, and ignore any error (since we can't do much
* about them anyway */
nRet = closesocket (hSock);
}
RemoveConn(lpstConn);
}
return (nRet);
} /* end CloseTCP() */
/*---------------------------------------------------------------
* Function:NewConn()
*
* Description: Create a new socket structure and put in list
*/
LPCONNDATA NewConn (SOCKET hSock,PSOCKADDR_IN lpstRmtName) {
int nAddrSize = sizeof(SOCKADDR);
LPCONNDATA lpstConnTmp;
LPCONNDATA lpstConn = (LPCONNDATA)0;
HLOCAL hConnData;
/* Allocate memory for the new socket structure */
hConnData = LocalAlloc (LMEM_ZEROINIT, sizeof(CONNDATA));
if (hConnData) {
/* Lock it down and link it into the list */
lpstConn = (LPCONNDATA) LocalLock(hConnData);
if (!lpstConnHead) {
lpstConnHead = lpstConn;// BQ NOTE: This Doesn't Work for some reason!
} else {
for (lpstConnTmp = lpstConnHead;
lpstConnTmp && lpstConnTmp->lpstNext;
lpstConnTmp = lpstConnTmp->lpstNext);
lpstConnTmp->lpstNext = lpstConn;
}
/* Initialize socket structure */
lpstConn->hSock = hSock;
_fmemcpy ((LPSTR)&(lpstConn->stRmtName),
(LPSTR)lpstRmtName, sizeof(SOCKADDR));
}
return (lpstConn);
} /* end NewConn() */
/*---------------------------------------------------------------
* Function: FindConn()
*
* Description: Find socket structure for connection using
* either socket or window as search key.
*/
LPCONNDATA FindConn (SOCKET hSock, HWND hwnd) {
LPCONNDATA lpstConnTmp;
for (lpstConnTmp = lpstConnHead;
lpstConnTmp;
lpstConnTmp = lpstConnTmp->lpstNext) {
if (hSock) {
if (lpstConnTmp->hSock == hSock)
break;
} else if (lpstConnTmp->hwnd == hwnd) {
break;
}
}
return (lpstConnTmp);
} /* end FindConn() */
/*---------------------------------------------------------------
* Function: RemoveConn()
*
* Description: Free the memory for socket structure
*/
void RemoveConn (LPCONNDATA lpstConn) {
LPCONNDATA lpstConnTmp;
HLOCAL hConnTmp;
if (lpstConn == lpstConnHead) {
lpstConnHead = lpstConn->lpstNext;
} else {
for (lpstConnTmp = lpstConnHead;
lpstConnTmp;
lpstConnTmp = lpstConnTmp->lpstNext) {
if (lpstConnTmp->lpstNext == lpstConn) {
lpstConnTmp->lpstNext = lpstConn->lpstNext;
}
}
}
RemoveTask (lpstConn->lpstTask);
hConnTmp = LocalHandle((void NEAR*)lpstConn);
LocalUnlock (hConnTmp);
LocalFree (hConnTmp);
} /* end RemoveConn() */
/*---------------------------------------------------------------
* Function: NewTask()
*
* Description: Register task with WinSock DLL by calling
* WSAStartup(), and create a new Task structure
*/
LPTASKDATA NewTask (HTASK hTask)
{
HANDLE hTaskData;
LPTASKDATA lpstTask = (LPTASKDATA)0L;
int nRet;
/* Register task with WinSock DLL */
nRet = WSAStartup(WSA_VERSION, &stWSAData);
if (nRet != 0) {
WSAperror(nRet, "WSAStartup()", hInst);
} else {
/* Allocate memory for a window structure */
hTaskData =
LocalAlloc(LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof(TASKDATA));
if (hTaskData) {
/* Convert it to a pointer */
lpstTask = (LPTASKDATA) LocalLock (hTaskData);
if (lpstTask) {
/* Initialize structure */
lpstTask->hTask = hTask;
lpstTask->nRefCount = 1;
/* Link this new record into our linked list */
if (!lpstTaskHead) {
lpstTaskHead = lpstTask;
} else {
LPTASKDATA lpstTaskTmp;
for (lpstTaskTmp = lpstTaskHead;
lpstTaskTmp->lpstNext;
lpstTaskTmp = lpstTaskTmp->lpstNext);
lpstTaskTmp->lpstNext = lpstTask;
}
} else {
/* Set error to indicate memory problems, and free memory */
WSASetLastError(WSAENOBUFS);
LocalFree(hTaskData);
}
} else {
/* Set error to indicate we couldn't allocate memory */
WSASetLastError(WSAENOBUFS);
}
}
return (lpstTask);
} /* end NewTask() */
/*---------------------------------------------------------------
* Function: FindTask()
*
* Description: Find Task structure using task handle as key.
*/
LPTASKDATA FindTask (HTASK hTask) {
LPTASKDATA lpstTaskTmp;
for (lpstTaskTmp = lpstTaskHead;
lpstTaskTmp;
lpstTaskTmp = lpstTaskTmp->lpstNext) {
if (lpstTaskTmp->hTask == hTask)
break;
}
return (lpstTaskTmp);
} /* end FindTask() */
/*---------------------------------------------------------------
* Function: RemoveTask()
*
* Description: Decrement the task reference count, and free
* the memory for task structure when ref count is zero.
*/
void RemoveTask (LPTASKDATA lpstTask) {
LPTASKDATA lpstTaskTmp;
HLOCAL hTaskTmp;
lpstTask->nRefCount--;
if (lpstTask->nRefCount <= 0) {
/* Reference count is zero, so free the task structure */
if (lpstTask == lpstTaskHead) {
lpstTaskHead = lpstTask->lpstNext;
} else {
for (lpstTaskTmp = lpstTaskHead;
lpstTaskTmp;
lpstTaskTmp = lpstTaskTmp->lpstNext) {
if (lpstTaskTmp->lpstNext == lpstTask)
lpstTaskTmp->lpstNext = lpstTask->lpstNext;
}
}
hTaskTmp = LocalHandle((void NEAR*)lpstTask);
LocalUnlock (hTaskTmp);
LocalFree (hTaskTmp);
/* Lastly, call WSACleanup() to deregister task with WinSock */
WSACleanup();
}
} /* end RemoveTask() */
#if 0
/*---------------------------------------------------------------
* Function: WSAperror()
*
* Description:
*/
void WSAperror (int WSAErr, LPSTR szFuncName, HANDLE hInst)
{
static char achErrBuf [ERR_SIZE]; /* buffer for errors */
static char achErrMsg [ERR_SIZE/2];
WSAErrStr (WSAErr, (LPSTR)achErrMsg, hInst);
wsprintf (achErrBuf, "%s failed,%-40c\n\n%s",
(LPSTR)szFuncName,' ',(LPSTR)achErrMsg);
/* Display error message as is (even if incomplete) */
MessageBox (GetActiveWindow(), (LPSTR)achErrBuf, (LPSTR)"Error",
MB_OK | MB_ICONHAND);
return;
} /* end WSAperror() */
/*-----------------------------------------------------------
* Function: WSAErrStr()
*
* Description: Given a WinSock error value, return error string
* NOTE: This function requires an active window to work if the
* instance handle is not passed.
*/
int WSAErrStr (int WSAErr, LPSTR lpErrBuf, HANDLE hInst) {
int err_len=0;
HWND hwnd;
if (!hInst) {
hwnd = GetActiveWindow();
#ifndef WIN32
hInst = GetWindowWord(hwnd, GWW_HINSTANCE);
#else
hInst = (HANDLE) GetWindowLong(hwnd, GWL_HINSTANCE);
#endif
}
if (WSAErr == 0) /* If error passed is 0, use the */
WSAErr = WSABASEERR; /* base resource file number */
if (WSAErr >= WSABASEERR) /* Valid Error code? */
/* get error string from the table in the Resource file */
err_len = LoadString(hInst, WSAErr, (LPSTR)lpErrBuf, ERR_SIZE/2);
return (err_len);
} /* end GetWSAErrStr() */
/*-----------------------------------------------------------
* Function: GetAddr()
*
* Description: Given a string, it will return an IP address.
* - first it tries to convert the string directly
* - if that fails, it tries o resolve it as a hostname
*
* WARNING: gethostbyname() is a blocking function
*/
u_long GetAddr (LPSTR szHost) {
LPHOSTENT lpstHost;
u_long lAddr = INADDR_ANY;
/* check that we have a string */
if (*szHost) {
/* check for a dotted-IP address string */
lAddr = inet_addr (szHost);
/* If not an address, then try to resolve it as a hostname */
if ((lAddr == INADDR_NONE) &&
(_fstrcmp (szHost, "255.255.255.255"))) {
lpstHost = gethostbyname(szHost);
if (lpstHost) { /* success */
lAddr = *((u_long FAR *) (lpstHost->h_addr));
} else {
lAddr = INADDR_ANY; /* failure */
}
}
}
return (lAddr);
} /* end GetAddr() */
/*---------------------------------------------------------------
* Function: GetPort()
*
* Description: Return a port number (in network order) from a
* string. May involve converting from ASCII to integer, or
* resolving as service name.
*
* NOTE: This function is limited in several respects:
* 1) it assumes the service name will not begin with an integer,
* although it *is* possible.
* 2) it assumes that the port number will be the same for both
* tcp & udp (it doesn't specify a protocol in getservbyname()).
* 3) if it fails, there must be an active window to allow
* WSAperror() to display the error text.
*/
u_short GetPort (LPSTR szService)
{
u_short nPort = 0; /* Port 0 is invalid */
LPSERVENT lpServent;
char c;
c = *szService;
if ((c>='1') && (c<='9')) {
/* Convert ASCII to integer, and put in network order */
nPort = htons((u_short)atoi (szService));
} else {
/* Resolve service name to a port number */
lpServent = getservbyname(szService, 0);
if (!lpServent) {
WSAperror (WSAGetLastError(), "getservbyname()", 0);
} else {
nPort = lpServent->s_port;
}
}
return (nPort);
} /* end GetPort() */
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -