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

📄 tcpip.cpp

📁 这个是应用了很多工程的TCPIP通讯库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// @doc
//
// @module	TcpIp.cpp | TcpIp class constructors/destructors
//
// This module contains the the constructor/destructors for the TcpIp
// class along with the Connect and Close member functions
//

// Maintenance:
//      
// Version      Date       Who          What
// -------   -----------  ------        -------------------------------------
// 7.0         04/24/97    blm          Created
// 7.1         02/20/98    mvs          Modified it for Tcp server support
// 7.1         05/20/98    mvs          Added UDP Support
//

#include <afx.h>
#include <WinSock2.h>
#include <ItkErr.h>
#include <TcpIp.h>


#define IO_INVALID_ADDRESS 0xFFFF

#define SERVER_ACPT_TIMEOUT			100
#define SERVER_RECV_TIMEOUT			5
#define SERVER_NO_RECV_TIMEOUT		200
#define SERVER_SHUT_TIMEOUT			3000
#define SERVER_SHUT_RETRY_TIMEOUT	1000

extern "C" {
EXPORT32 BOOL WINAPI DllMain( HANDLE hInstance, DWORD dwReason, VOID *pReserved )
{
	BOOL bSuccess = 1;

	int  nReturnVal;


	switch ( dwReason )
	{
		case DLL_PROCESS_ATTACH:
		{
			WORD    wVerReq;

			WSADATA sWsdata;


			wVerReq = MAKEWORD(2,2);
	
			nReturnVal = WSAStartup(wVerReq, &sWsdata);
			if (nReturnVal)
			{
				// LogError here ?
			}
		
			break;
		}
		case DLL_PROCESS_DETACH:
			nReturnVal = WSACleanup();
			if (nReturnVal)
			{
				// LogError here
			}

			break;

		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
			break;
		default:
			break;
	}

	return( bSuccess );

	pReserved = pReserved;
}	// End of DllMAin()
} // Extern "C"

//
// 
// @mfunc <c CTcpIp> constructor for this class. This function 
//                  simply initializes all the data members,
//                  initializes a critical section used throughout
//                  the object and 
//                  
//
// @parm  IN const TCHAR * | pszAppName	| Name of the driver that is using the object
//
// @parm  IN const TCHAR * | szIpAddress| Ip AddressName of the device to be connected
//
// @parm  IN const BOOL	   | bClient	| The object to be initialized in Client Mode
//										  or Server Mode. TRUE=Client, FALSE=Server
//										  In Client mode - this object initiates the
//										  the connection request
//										  In Server mode - this object waits for
//										  a client to initiate the connection request
//
// @parm  IN const BOOL	   | bTcp		| The object to be initialized using 
//										 Tcp or Udp protocol. TRUE=Tcp, FALSE=Udp
//
// @parm  IN void | CALLBACK *lpfnRcvCallback | Callback Function supplied by the caller to
//                                            allow the CTcpIp object to return back the data
//												in client mode
//                                          received from an non-blocking asynchronous recv call.
//                                          function will just display the message.
//											The prototype of the completion routine is as follows: 
//
//											void CALLBACK CompletionROUTINE(
//														IN DWORD dwError, 
//														IN DWORD cbTransferred, 
//														IN LPWSAOVERLAPPEDlpOverlapped, 
//														IN DWORD dwFlags
//														); 
//
// @parm  IN void*| pCallbackParam	| Callback Parameter which is used 
//											by the receive Callback function
//
// @parm  IN OPTIONAL void | lpfnMsgDisplay | Function supplied by the caller to
//                                            allow the CTcpIp object to report
//                                            events. By default, its assumed that this
//                                            function will just display the message.
// 
// @parm  IN OPTIONAL void | CALLBACK *lpfnTcpServerCallback | Callback Function supplied by the caller to
//                                            allow the CTcpIp object in server mode
//                                            to send back the data received from a client
// 
// @parm  IN OPTIONAL void | CALLBACK *lpfnUdpServerCallback | Callback Function supplied by the caller to
//                                            allow the CTcpIp object in server mode
//                                            to send back the data received from a client
// 
// @parm  IN OPTIONAL unsigned short int| uListenPortNumber | The Port Number for listening for 
//															a connection.(needed only when 
//															object is instanciated in server mode).
// 
// @parm  IN OUT OPTIONAL unsigned char* | pServerBuf | Buffer for storing data received from a
//														client (needed only when object is 
//														instanciated in server mode).
// 
// @parm  IN OPTIONAL DWORD  | dwBufSize | Size of Buffer for storing data received from a
//											client (needed only when object is 
//											instanciated in server mode).
// 
EXPORT32 CTcpIp::CTcpIp(IN const TCHAR *szAppName,
						IN const TCHAR *szIpAddress,
						IN const BOOL bClient,
						IN const BOOL bTcp,
						IN void  (CALLBACK *lpfnRcvCallback)(DWORD dwError, DWORD dwTransferred, 
												 		     LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags),
						IN void  *pCallbackParam,
						IN OPTIONAL void (*lpfnMsgDisplay)(const TCHAR *szString),
						IN OPTIONAL void (CALLBACK *lpfnTcpServerCallback)(void *pCallbackParam, SOCKET ClientSocket, DWORD dwActualSize),
						IN OPTIONAL void (CALLBACK *lpfnUdpServerCallback)(void *pCallbackParam, SOCKADDR ClientSockaddr, DWORD dwActualSize),
						IN OPTIONAL const unsigned short int uListenPortNumber,
						IN OUT OPTIONAL unsigned char *pServerBuf,
						IN OPTIONAL DWORD dwBufSize)
{
	//
	// Check if application is a client or server, Tcp or Udp
	//
	m_bClient	= bClient;
	m_bTcp		= bTcp;
	memset((void *)&m_WriteOverlapped, 0, sizeof(OVERLAPPED));
	memset((void *)&m_ReadOverlapped, 0, sizeof(OVERLAPPED));
	memset((void *)&m_sSocketAddress, 0, sizeof(SOCKADDR));
	memset((void *)&m_sRemoteAddress, 0, sizeof(SOCKADDR));

	//	Save the callback parameter
	m_ReadOverlapped.hEvent = (HANDLE)pCallbackParam;

	strcpy(m_szAppName, szAppName);
	strcpy(m_szIpAddress, szIpAddress);

	m_lpfnMsgDisplay		= lpfnMsgDisplay;
	m_lpfnRcvCallback		= lpfnRcvCallback;
	m_nSocketAddressSize	= sizeof(SOCKADDR);
	m_nRemoteAddressSize	= sizeof(SOCKADDR);

	if (m_bClient)
	{
		// This is a client. Process accordingly
		DWORD  dwError;
		struct hostent *hp = NULL;
		unsigned long lIpAddress = 0;

		m_lIpAddress		= INADDR_NONE;
		m_uPortNumber		= 0;
		m_Socket			= INVALID_SOCKET;
		m_sHost				= NULL;
		m_bStop				= FALSE;

		m_dwConnectState	= DRV_NOT_CONNECTED;
		m_bSocketState		= SOCKET_NOT_CREATED;
		m_dwStatus			= IO_CREATE_SOCKET;

		m_dwReadThreadId	= 0;
		m_hReadThread		= (HANDLE)NULL;

		
		//
		//  Convert the Ip address to a 32-bit integer value
		//
		lIpAddress = GetAddr(szIpAddress);
		if (INADDR_NONE != lIpAddress)
		{
			m_dwStatus        = IO_SUCCESS;
			m_lIpAddress	  = lIpAddress;
	
			dwError = Open();
			if (IO_SUCCESS != dwError)
			{
				//
				//  Error in Creating Socket
				//
				m_dwStatus = dwError;
			}
		}
		else
		{
			m_dwStatus = IO_INVALID_ADDRESS;
		}
	}// End of if(bClient) loop
	else
	{
		// This is a server. Process accordingly

		// Set the stop flag and signal the event for the threads
		m_bStop					= FALSE;
		m_Socket				= INVALID_SOCKET;
		m_bSocketState			= SOCKET_NOT_CREATED;
		m_dwConnectState		= DRV_NOT_CONNECTED;
		m_dwListenThreadId		= 0;
		m_hListenThread			= (HANDLE)NULL;
		m_uPortNumber			= uListenPortNumber;
		m_lpfnTcpServerCallback	= lpfnTcpServerCallback;
		m_lpfnUdpServerCallback	= lpfnUdpServerCallback;
		m_pServerBuf			= pServerBuf;
		m_dwServerBufSize		= dwBufSize;
		m_pCallbackParam		= (HANDLE)pCallbackParam;


		// Initialize the Critical section
		InitializeCriticalSection(&m_hConnectionListCS);

		if (uListenPortNumber)
		{
			m_hListenThread	= CreateThread(NULL,
									 0,
									 (LPTHREAD_START_ROUTINE)ListenHandler, 
									 (LPVOID)this, 
									 0, 
									 &m_dwListenThreadId);
		}
	
	}// End of else-if(bClient) loop
}

//
// @mfunc   <c CTcpIp> destructor. Calls the Close member function
//          to take care of cleaning up resources created by the Open
//          member function, then frees the resources created by the
//          constructor.
//
EXPORT32 CTcpIp::~CTcpIp()
{
	if (m_bClient)
	{
		Close();
	}
	else
	{
		m_bStop = TRUE;

		DWORD dwErrorCode = IO_SUCCESS, lpExitCode = 0;
		BOOL bRet = FALSE;
		int	nError = 0;
		int nCounter = 0;

		Sleep(SERVER_SHUT_TIMEOUT);

		nCounter = 0;
		while ((this->m_bSocketState == SOCKET_CLOSING) && (nCounter < MAX_WAIT_COUNT))
		{
			Sleep(SERVER_SHUT_RETRY_TIMEOUT);
			nCounter++;
		}

		if (m_hListenThread != (HANDLE) NULL)
		{
			bRet = GetExitCodeThread(m_hListenThread, &lpExitCode);
			if (bRet)
			{
				if (lpExitCode == STILL_ACTIVE)
				{
					TerminateThread(m_hListenThread, 0);
				}
			}
			else
			{
				TerminateThread(m_hListenThread, 0);
			}
		}

		if (m_hReceiveThread != (HANDLE) NULL)
		{
			bRet = GetExitCodeThread(m_hReceiveThread, &lpExitCode);
			if (bRet)
			{
				if (lpExitCode == STILL_ACTIVE)
				{
					TerminateThread(m_hReceiveThread, 0);
				}
			}
			else
			{
				TerminateThread(m_hReceiveThread, 0);
			}
		}

		CloseAllConnections();

		CloseHandle(m_hListenThread);
		CloseHandle(m_hReceiveThread);

		DeleteCriticalSection(&m_hConnectionListCS);
	}
}

//
//
//	FUNCTION:	Open
//
//	TcpIp Client Mode
//	This function creates the socket for the TCP client and
//	sets the proper modes for the socket
//
// Return Value: IO_SUCESS				- If successful
//				 IO_CLIENT_ERR			- If object not in client mode
//               IO_CREATE_SOCKET		- If error creating a socket
//
DWORD CTcpIp::Open()
{
	DWORD dwErrorCode = IO_SUCCESS;

	// This is a client not server. Just go away.
	if (!this->m_bClient)
	{
		dwErrorCode = IO_CLIENT_ERR;
		return(dwErrorCode);
	}

	if (this->m_Socket != INVALID_SOCKET)
	{
		if (this->m_bSocketState == SOCKET_CREATED)
		{
			return(dwErrorCode);
		}
		else
		{
			TRACE("TCP: Failed to create a new socket\n");
			Close();
		}
	}

	//
	// Create Socket. By default it is in Blocking Mode
	//
	if (m_bTcp)
	{
		this->m_Socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
	}
	else
	{
		this->m_Socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
	}

    if (INVALID_SOCKET == this->m_Socket)
	{
		dwErrorCode = IO_CREATE_SOCKET;
		this->m_bSocketState = SOCKET_CLOSED;
		m_Socket = INVALID_SOCKET;
		TRACE("TCP: Open- WSASocket() failed to create a new socket, Error = %d\n",WSAGetLastError());
	}
	else
	{
		int	opt_val = 1,
			nError,
			nTxBufSize = TCP_INPUT_QUEUE_SIZE,
			nRxBufSize = TCP_OUTPUT_QUEUE_SIZE;

		nError = setsockopt(this->m_Socket, SOL_SOCKET, SO_DONTLINGER, (char *)&opt_val, sizeof(opt_val));

		if (m_bTcp)
		{
			nError = setsockopt(this->m_Socket, IPPROTO_TCP, TCP_NODELAY, (char *)&opt_val, sizeof(opt_val)) ;
		}

		this->m_bSocketState = SOCKET_CREATED;
		TRACE("TCP: New socket created\n");
	}

	
	return(dwErrorCode);
}

//
// @mfunc   Close - In TcpIp Client Mode
//			This function frees all the resources created by the
//          Open member function. This primarily consists of shutdown
//			for connected socket, internal buffers and events. 
//			It also is responsible for 
//          stopping the asynchronous read thread if one exists.
//
// @parm   None | 
//
// @rvalue IO_SUCCESS | If successful
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::Close(void)
{
	DWORD dwErrorCode = IO_SUCCESS, lpExitCode = 0;

	BOOL bRet = FALSE;
	int	nError = 0;

	// This is a client not server. Just go away.
	if (!this->m_bClient)
	{
		dwErrorCode = IO_CLIENT_ERR;
		return(dwErrorCode);
	}

	if (m_hReadThread != (HANDLE) NULL)
	{
		bRet = GetExitCodeThread(m_hReadThread, &lpExitCode);
		if (bRet)
		{
			if (lpExitCode == STILL_ACTIVE)
			{
				TerminateThread(m_hReadThread, 0);
			}
		}
		else
		{
			TerminateThread(m_hReadThread, 0);
		}

		CloseHandle(m_hReadThread);
		m_hReadThread = (HANDLE) NULL;
	}

	//
	//	If Socket not created or already closed; then just return
	//
	if (m_Socket == INVALID_SOCKET)
	{
		this->m_bSocketState = SOCKET_CLOSED;
		return(dwErrorCode);
	}
	
	//
	//	Close connection to this socket.
	//
	this->DisConnect();

	//

⌨️ 快捷键说明

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