📄 tcpip.cpp
字号:
OUT TCHAR *szSORcvBuf, IN OUT int *dpSORcvBufSize,
OUT int *dpLastError)
{
DWORD dwErrorCode = IO_SUCCESS;
int nError;
// This is a client not server. Just go away.
if (!this->m_bClient)
{
dwErrorCode = IO_CLIENT_ERR;
return(dwErrorCode);
}
//
// If Socket not created or already closed; then just return
// If you add any other states then you may want to change this.
//
if (this->m_bSocketState != SOCKET_CREATED)
{
dwErrorCode = IO_SOCKET_ERROR;
return(dwErrorCode);
}
//
// Get socket options on this socket
//
if (((nError = getsockopt (this->m_Socket, SOL_SOCKET, SO_SNDBUF, (char *) szSOSendBuf, (int *)dpSOSendBufSize )) == SOCKET_ERROR) ||
((nError = getsockopt (this->m_Socket, SOL_SOCKET, SO_RCVBUF, (char *) szSORcvBuf, (int *)dpSORcvBufSize )) == SOCKET_ERROR) )
{
//
// Unable to get the socket options
//
*dpLastError = WSAGetLastError();
dwErrorCode = IO_SOCKET_OPTION_ERROR;
}
return(dwErrorCode);
}
//
// @mfunc GetSocketTmoOptions - In Tcp/Udp Client Mode
// This function gets the common socket Timeout options
//
// @parm OUT TCHAR * | szRcvTmo | Receive Buffer Timeout period
//
// @parm IN OUT int * | dpRcvTmoSize | Sizeof szRcvTmo
//
// @parm OUT TCHAR * | szSendTmo | Send Buffer Timeout period
//
// @parm IN OUT int * | dpSendTmoSize | Sizeof szSendTmo
//
// @parm OUT int * | dpLastError | Last Error Number
//
// @rvalue IO_SUCCESS | If successful
//
// @rvalue IO_SOCKET_OPTION_ERROR | If fails
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
// @rvalue IO_SOCKET_ERROR | If Client Socket Invalid
//
EXPORT32 DWORD CTcpIp::GetSocketTmoOptions (OUT TCHAR *szRcvTmo, IN OUT int *dpRcvTmoSize,
OUT TCHAR *szSendTmo, IN OUT int *dpSendTmoSize,
OUT int *dpLastError)
{
DWORD dwErrorCode = IO_SUCCESS;
int nError;
// This is a client not server. Just go away.
if (!this->m_bClient)
{
dwErrorCode = IO_CLIENT_ERR;
return(dwErrorCode);
}
//
// If Socket not created or already closed; then just return
// If you add any other states then you may want to change this.
//
if (this->m_bSocketState != SOCKET_CREATED)
{
dwErrorCode = IO_SOCKET_ERROR;
return(dwErrorCode);
}
//
// Get socket options on this socket
//
if (((nError = getsockopt (this->m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *) szRcvTmo, (int *)dpRcvTmoSize)) == SOCKET_ERROR) ||
((nError = getsockopt (this->m_Socket, SOL_SOCKET, SO_SNDTIMEO, (char *) szSendTmo,(int *)dpSendTmoSize)) == SOCKET_ERROR))
{
//
// Unable to get the socket options
//
*dpLastError = WSAGetLastError();
dwErrorCode = IO_SOCKET_OPTION_ERROR;
}
return(dwErrorCode);
}
//
// @mfunc GetConnectState - In Tcp/Udp Client Mode
// This function gets the Connection State of the object
//
// @parm void
//
// @rvalue DRV_CONNECTED | If object currently connected
//
// @rvalue DRV_CONNECTING | If connection still in progress
//
// @rvalue DRV_CONNECT_FAILED | If connection failed
//
// @rvalue DRV_NOT_CONNECTED | If not connected
//
EXPORT32 DWORD CTcpIp::GetConnectState(void)
{
return(this->m_dwConnectState);
}
//
// 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 to resolve it as a hostname
//
// WARNING: gethostbyname() is a blocking function
//
unsigned long CTcpIp::GetAddr(IN const TCHAR *szHost)
{
LPHOSTENT lpstHost;
unsigned 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) &&
(strcmp (szHost, "255.255.255.255")))
{
lpstHost = gethostbyname(szHost);
if (lpstHost)
{
lAddr = *((unsigned long *)(lpstHost->h_addr));
}
else
{
lAddr = INADDR_NONE;
}
}
}
return (lAddr);
}
//
//
// FUNCTION: ReportConnectError
//
// Description: Displays a connection message if successfully connected
// or displays a error message if connect fails.
//
//
void CTcpIp::ReportConnectError(IN TCHAR *szMsg, IN BOOL bSuccess)
{
TCHAR szErrorMsg[256];
if (bSuccess)
{
sprintf(szErrorMsg, "Successfully connected to %s port %u",
this->m_szIpAddress, this->m_uPortNumber);
TRACE("TCP: Successfully connected to %s port %u",this->m_szIpAddress, this->m_uPortNumber);
}
else
{
sprintf(szErrorMsg, "Error connecting to %s port %u: %s",
this->m_szIpAddress, this->m_uPortNumber, szMsg);
TRACE("TCP: Error connecting to %s port %u",this->m_szIpAddress, this->m_uPortNumber);
}
DisplayMessage(szErrorMsg);
}
//
//
// FUNCTION: (LPTHREAD_START_ROUTINE)ListenHandler
//
// This function is the start address for the
// listen thread
//
BOOL CTcpIp::ListenHandler(IN LPVOID ptr)
{
CTcpIp *pObj = (CTcpIp *)ptr;
if (pObj == NULL)
{
ExitThread(FALSE);
return(FALSE);
}
// This is a client not server. Just go away.
if (pObj->m_bClient)
{
ExitThread(FALSE);
return(FALSE);
}
DWORD dwErrorCode = IO_SUCCESS;
if (pObj->m_Socket != INVALID_SOCKET)
{
dwErrorCode = IO_CREATE_SOCKET;
pObj->m_bSocketState = SOCKET_CLOSED;
pObj->m_Socket = INVALID_SOCKET;
TRACE("TCP: Failed to create a new socket\n");
}
int nError = 0;
int nLastError = 0;
unsigned long uNonBlock = 1;
struct sockaddr_in sClientSockAddress;
SOCKET NewSocket;
//
// Create a Listen Socket. By default it is in Blocking Mode
//
if (pObj->m_bTcp)
{
pObj->m_Socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
}
else
{
pObj->m_Socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
}
if (INVALID_SOCKET == pObj->m_Socket)
{
nLastError = WSAGetLastError();
dwErrorCode = IO_CREATE_SOCKET;
pObj->m_bSocketState = SOCKET_CLOSED;
pObj->m_Socket = INVALID_SOCKET;
TRACE("TCP: Open- WSASocket() failed to create a new socket, Error = %d\n",WSAGetLastError());
ExitThread(nLastError);
return(FALSE);
}
else
{
int opt_val = 1,
nError,
nTxBufSize = TCP_INPUT_QUEUE_SIZE,
nRxBufSize = TCP_OUTPUT_QUEUE_SIZE;
nError = setsockopt(pObj->m_Socket, SOL_SOCKET, SO_DONTLINGER, (char *)&opt_val, sizeof(opt_val));
if (pObj->m_bTcp)
{
nError = setsockopt(pObj->m_Socket, IPPROTO_TCP, TCP_NODELAY, (char *)&opt_val, sizeof(opt_val));
}
pObj->m_bSocketState = SOCKET_CREATED;
TRACE("TCP: New socket created\n");
}
//
// Set to non-blocking mode
//
nError = ioctlsocket(pObj->m_Socket, FIONBIO, &uNonBlock);
if (SOCKET_ERROR == nError)
{
pObj->m_dwConnectState = DRV_SOCKET_ERROR;
}
else
{
pObj->m_dwConnectState = DRV_SOCKET_NONBLOCKING;
}
pObj->m_sSocketAddress.sin_family = AF_INET;
pObj->m_sSocketAddress.sin_addr.s_addr = INADDR_ANY;
pObj->m_sSocketAddress.sin_port = (unsigned short) htons(pObj->m_uPortNumber);
//
// Bind the socket to the local name and ipaddress
//
nError = bind(pObj->m_Socket, (LPSOCKADDR) &(pObj->m_sSocketAddress), sizeof(sockaddr_in));
if (SOCKET_ERROR == nError)
{
nLastError = WSAGetLastError();
pObj->m_dwConnectState = DRV_SOCKET_ERROR;
pObj->m_bSocketState = SOCKET_CLOSING;
pObj->CloseAllConnections();
ExitThread(nLastError);
return(FALSE);
}
if (!pObj->m_bTcp)
{
//
// For Udp, start the receive handler
//
if (!pObj->m_bStop)
{
pObj->m_hReceiveThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ReceiveUdpHandler,
(LPVOID)ptr,
0,
&pObj->m_dwReceiveThreadId);
}
else
{
if (pObj->m_Socket != INVALID_SOCKET)
{
//
// Close the socket
//
nError = closesocket(pObj->m_Socket);
pObj->m_Socket = INVALID_SOCKET;
}
pObj->m_dwConnectState = DRV_SOCKET_ERROR;
ExitThread(nLastError);
return(FALSE);
}// End of else loop
}
else
{
//
// For Tcp
// Listen for connection.
//
nError = listen(pObj->m_Socket, MAX_LISTEN_QUEUE);
if (SOCKET_ERROR == nError)
{
nLastError = WSAGetLastError();
if (pObj->m_Socket != INVALID_SOCKET)
{
//
// Close the socket
//
nError = closesocket(pObj->m_Socket);
pObj->m_Socket = INVALID_SOCKET;
}
pObj->m_dwConnectState = DRV_SOCKET_ERROR;
ExitThread(nLastError);
return(FALSE);
}
CONNECION_DATA *pConnectionInfo = NULL;
// int nMaxEntries = 0;
int nTotalEntries = 0;;
int nLength = sizeof(sockaddr);
BOOL bFirstTimeFlag = TRUE;
DWORD dwTimeStart = 0L, dwTimeCurrent = 0L, dwTimeDiff = 0L;
dwTimeStart = GetTickCount();
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
while (!pObj->m_bStop)
{
#ifdef _DEBUG
if (bFirstTimeFlag)
{
TRACE("TCP: Server : In accept connection loop. Timer = %ld \n", dwTimeStart);
bFirstTimeFlag = FALSE;
}
else
{
dwTimeCurrent = GetTickCount();
dwTimeDiff = dwTimeCurrent - dwTimeStart;
// if time difference > 60secs. display message in trace window
if (dwTimeDiff > (DWORD)60000L)
{
TRACE("TCP: Server : Timer Up. In accept connection loop. %ld\n", dwTimeCurrent);
dwTimeStart = dwTimeCurrent;
}
}// end else loop
#endif // _DEBUG
pObj->m_bSocketState = SOCKET_ACCEPTING;
if ((NewSocket = accept(pObj->m_Socket, (LPSOCKADDR)&sClientSockAddress, &nLength))
== INVALID_SOCKET)
{
nLastError = WSAGetLastError();
switch (nLastError)
{
// A successful WSAStartup must occour
case WSANOTINITIALISED :
// The network subsystem has failed
case WSAENETDOWN :
// The addrlen parameter is too small or addr is not a valid part of
// the user address space
case WSAEFAULT :
// The listen function was not invoked prior to accept.
case WSAEINVAL :
// The descriptor is not a socket.
case WSAENOTSOCK :
// The referenced socket is not a type that supports
// connection-oriented service.
case WSAEOPNOTSUPP :
// A blocking Windows Sockets call was canceled through
// WSACancelBlockingCall
case WSAEINTR :
// No buffer space is available.
case WSAENOBUFS :
// The queue is nonempty upon entry to accept and
// there are no descriptors available.
case WSAEMFILE :
pObj->m_bSocketState = DRV_ACCEPT_ERROR;
break;
// A blocking Windows Sockets call is in progress,
// or the service provider is still processing a callback function.
case WSAEINPROGRESS :
break;
// The socket is marked as nonblocking and
// no connections are present to be accepted.
case WSAEWOULDBLOCK :
break;
// default. return value unknown.
// just go on.
default:
break;
}// End of switch statement
if (pObj->m_bSocketState == DRV_ACCEPT_ERROR)
{
// Error occoured. break out of while loop. Cleanup and shutdown
TRACE("TCP: Server Failed to accept connection. WSALastError = %d \n", nLastError);
break;
}
else
{
// Continue to accept connections.
pObj->m_bSocketState = SOCKET_ACCEPTING;
// sleep for a small period before looping back
Sleep(SERVER_ACPT_TIMEOUT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -