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

📄 tcpip.cpp

📁 这个是应用了很多工程的TCPIP通讯库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	//  Close the socket
	//
	nError = closesocket(this->m_Socket);
	if (SOCKET_ERROR == nError)
	{
		TCHAR szMsg[256];

		nError = WSAGetLastError();
		TRACE("TCP: Attempt to close socket returned error: %d\n", nError);
		sprintf(szMsg, 
				"Attempt to close socket for %s returned error: %d", 
				m_szIpAddress, 
				nError);
		DisplayMessage(szMsg);
	}
	else
	{
		TRACE("TCP: Socket closed\n");
	}
	
	m_Socket = INVALID_SOCKET;
	this->m_bSocketState = SOCKET_CLOSED;
	this->m_dwConnectState = DRV_NOT_CONNECTED;
		
	return(dwErrorCode);
}


//
// @mfunc   Connect - In TcpIp Client Mode
//			This function connects the client to the specified server
//
// @parm   unsigned short int |uPortNumber | port number of server application
//
// @rvalue DRV_CONNECTED | If connection successful
//
// @rvalue DRV_CONNECTING | If connection still in progress
//
// @rvalue DRV_CONNECT_FAILED | If connection failed
//
// @rvalue DRV_NOT_CONNECTED | If cannot connect
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::Connect(unsigned short int uPortNumber)
{
	DWORD  dwErrorCode = IO_SUCCESS;

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

	if (m_Socket == INVALID_SOCKET)
	{
		dwErrorCode = Open();
		if (IO_SUCCESS != dwErrorCode)
		{
			//
			//  Error in Creating Socket
			//
			m_dwStatus = dwErrorCode;
		}
	}

	//
	//	If this is a UDP the you do not need connect.
	//	Just copy the parameters for the address and port
	if (!this->m_bTcp)
	{
		m_uPortNumber = uPortNumber;

        if (this->m_lIpAddress != INADDR_ANY)
		{ 
			this->m_sSocketAddress.sin_family           = AF_INET;
			this->m_sSocketAddress.sin_addr.S_un.S_addr = this->m_lIpAddress;
			this->m_sSocketAddress.sin_port             = htons(this->m_uPortNumber);
		}

		m_dwConnectState = DRV_CONNECTED;
		return(m_dwConnectState);
	}

	// If this is a TCP then continue connecting
	switch (m_dwConnectState)
	{
	case DRV_CONNECTED:
	case DRV_CONNECTING:
	case DRV_CONNECT_FAILED:
		break;

	case DRV_NOT_CONNECTED:
	{

		DWORD lpExitCode = 0;
		BOOL bRet = FALSE;

		m_uPortNumber = uPortNumber;
		m_dwConnectState = DRV_CONNECTING;

		if (m_hReadThread != NULL)
		{
			bRet = GetExitCodeThread(m_hReadThread, &lpExitCode);
			if (bRet)
			{
				if (lpExitCode == STILL_ACTIVE)
				{
					return(m_dwConnectState);
				}
				else
				{
					CloseHandle(m_hReadThread);
					m_hReadThread = (HANDLE) NULL;
				}
			}
			else
			{
				lpExitCode = GetLastError();
				m_dwConnectState = DRV_CONNECT_FAILED;
				return(m_dwConnectState);
			}
		}

		m_hReadThread = CreateThread(NULL,
									 0,
									 (LPTHREAD_START_ROUTINE)ConnectHandler, 
									 (LPVOID)this, 
									 0, 
									 &m_dwReadThreadId);
	}

	default:
		break;
	}

	return(m_dwConnectState);
}


//
//
//	FUNCTION:	(LPTHREAD_START_ROUTINE)ConnectHandler
//
//	This function is the start address for the 
//	connection thread
//
BOOL CTcpIp::ConnectHandler(IN LPVOID ptr)
{
	CTcpIp			*pObj = (CTcpIp *)ptr;

	int				nError;

	unsigned long	uNonBlock = 0;
	
	// This is a client not server. Just go away.
	if (!pObj->m_bClient)
	{
		pObj->m_dwConnectState = DRV_NOT_CONNECTED;
		return(FALSE);
	}

	//
	//	If this is a UDP the you do not need connect.
	if (!pObj->m_bTcp)
	{
		return(FALSE);
	}

	if (pObj->m_Socket == INVALID_SOCKET)
	{
		pObj->m_dwConnectState = DRV_CONNECT_FAILED;
		TRACE("TCP: Connect Handler Failed. Socket NULL ...\n");
		return(FALSE);
	}

	pObj->m_dwConnectState = DRV_CONNECTING;
	TRACE("TCP: Connecting ...\n");

	//
	//	Set to blocking mode. We do the connect first and 
	//	then set it to non-blocking later on.
	//
	nError = ioctlsocket(pObj->m_Socket, FIONBIO, &uNonBlock);
	if (SOCKET_ERROR == nError)
	{	
//		pObj->m_dwConnectState = DRV_CONNECT_FAILED;
	}


	if (NULL == pObj->m_sHost)
	{
		pObj->m_sHost = gethostbyaddr((char *)&pObj->m_lIpAddress, 
								      sizeof(pObj->m_lIpAddress), 
									  AF_INET);
		if (NULL == pObj->m_sHost)
		{
			pObj->m_dwConnectState = DRV_CONNECT_FAILED;
			pObj->ReportConnectError("Unable to resolve Ip Address", FALSE);
			return(FALSE);
		}
	}
		
	if (NULL != pObj->m_sHost)
	{
		TCHAR szConnectMsg[256];

		sprintf(szConnectMsg, 
				"Attempting connection to %s  at port %d", 
				pObj->m_szIpAddress, 
				pObj->m_uPortNumber);
		pObj->DisplayMessage(szConnectMsg);

		pObj->m_sSocketAddress.sin_family           = AF_INET;
		pObj->m_sSocketAddress.sin_addr.S_un.S_addr = pObj->m_lIpAddress;
		pObj->m_sSocketAddress.sin_port             = htons(pObj->m_uPortNumber);

		nError = connect(pObj->m_Socket, (LPSOCKADDR)&pObj->m_sSocketAddress,
						 sizeof(struct sockaddr_in));
		if (SOCKET_ERROR == nError)
		{
			DWORD dwConnectError = WSAGetLastError();
			switch (dwConnectError)
			{
			case WSAEADDRINUSE: 
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("The specified address is already in use", FALSE);
				break;
			case WSAEADDRNOTAVAIL: 
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("The specified address is not available from the local machine", FALSE); 
				break;
			case WSAEAFNOSUPPORT: 
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("Addresses in the specified family cannot be used with this socket", FALSE); 
				break;
			case WSAECONNREFUSED:
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("The attempt to connect was forcefully rejected", FALSE);
				break;
			case WSAENETUNREACH: 
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("The network cannot be reached from this host at this time", FALSE); 
				break;
			case WSAENOBUFS: 
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("No buffer space is available. The socket cannot be connected", FALSE);
				break;
			case WSAETIMEDOUT: 
				pObj->m_dwConnectState = DRV_CONNECT_FAILED;
				pObj->ReportConnectError("Attempt to connect timed out without establishing a connection", FALSE);
				break;
			case WSAEISCONN:
				pObj->m_dwConnectState = DRV_CONNECTED;
				pObj->ReportConnectError("Attempt to connect but already connected", FALSE);
				break;
			case WSAEALREADY:
				pObj->m_dwConnectState = DRV_CONNECTING;
				pObj->ReportConnectError("Already in progress", FALSE);
				break;
			case WSAEWOULDBLOCK:
				pObj->m_dwConnectState = DRV_CONNECTING;
				pObj->ReportConnectError("It would have blocked",FALSE);
				break;

			default:
				{
					TCHAR szCntErr[80];
					sprintf(szCntErr, "connect() failed for unknown reason: %d", dwConnectError);
					pObj->m_dwConnectState = DRV_CONNECT_FAILED;
					pObj->ReportConnectError(szCntErr, FALSE);
				}
				break;
			}
		}
		else
		{
			//
			//	Device Connected - Successfully. 
			//	Change State to Connected.
			//
			pObj->m_dwConnectState = DRV_CONNECTED;
			pObj->ReportConnectError(NULL, TRUE);

			//
			//	Set to non-blocking mode
			//
			uNonBlock = 1;
			nError = ioctlsocket(pObj->m_Socket, FIONBIO, &uNonBlock);
			if (SOCKET_ERROR == nError)
			{
				pObj->DisplayMessage("Unable to set socket to non-blocking mode");
			}
		}
	}

	return(TRUE);
}


//
// @mfunc   DisConnect - In TcpIp Client Mode
//			This function does a shutdown for the connected socket,
//
// @parm   none
//
// @rvalue IO_SUCCESS | If successful
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::DisConnect()
{
	DWORD dwErrorCode = IO_SUCCESS;

	BOOL bOption = 1;
	int	nError = 0, nIndex = 0;
	char szDiscardBuf[INPUT_BUFFER_SIZE];


	// 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)
	{
		return(dwErrorCode);
	}
	
	//
	//	Set to non-blocking mode, (just in case...)
	//
	unsigned long uNonBlock = 1;
	nError = ioctlsocket(this->m_Socket, FIONBIO, &uNonBlock);

	if (m_bTcp)
	{
		//	Half-close the connection to close neatly (NOTE: we ignore the
		//  return from this function because some BSD-based WinSock 
		//  implementations fail shutdown() with WSAEINVAL if a TCP reset 
		//  has been recieved.  In any case, if it fails it means the 
		//  connection is already closed anyway, so it doesn't matter.)
		nError = shutdown(this->m_Socket, SD_SEND);

		//  Discard any data received on this socket
		//	until no more data, EOF or error.
		for (nError = 1; (nError && (nError != SOCKET_ERROR));)
		{
			//	If no data recieved on this socket recv() will return zero.
			//	If socket is invalid, already closed or some other problem occoured
			//	recv() will return SOCKET_ERROR
			//	else if there is more data, recv() will  return a non-zero value.
			nError = recv(this->m_Socket, (LPSTR)szDiscardBuf, INPUT_BUFFER_SIZE, 0);
			Sleep(5);
		}// End of for loop
	}// End of if (m_bTcp) loop
	//
	//  Set the DONTLINGER option so it connection will be aborted and 
	//  return immediately.
	//
	setsockopt(this->m_Socket, SOL_SOCKET, SO_DONTLINGER, (TCHAR *)&bOption, sizeof(bOption));

	this->m_dwConnectState = DRV_NOT_CONNECTED;

	return(dwErrorCode);
}

//
// @mfunc   Send - (Overloaded) In TcpIp Client Mode
//			This function sends request or data to a connected server
//
// @parm   IN unsigned char * | pBuffer | Buffer to send
//
// @parm   IN DWORD | dwSize | Number of bytes to send
//
// @rvalue IO_SUCCESS | If successful
//
// @rvalue IO_SEND_ERROR | If send failed
//
// @rvalue IO_CLIENT_ERR | If object not in client mode
//
EXPORT32 DWORD CTcpIp::Send(IN unsigned char *pBuffer, IN DWORD dwSize)
{
	int nError;

	DWORD dwBytesSent = 0, dwBytesLeftToSend, dwBytesTotalSent = 0,
		  dwErrorCode = IO_SUCCESS;

	WSABUF sNetBuffer;
	TCHAR szMsg[256];

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

	if (DRV_CONNECTED == this->m_dwConnectState)
	{
		dwBytesLeftToSend = dwSize;

		sNetBuffer.len = dwSize;
		sNetBuffer.buf = (char *)pBuffer;

		//
		//	Now actually send data.
		//	Note:	This can be used for both TCP and UDP protocols.
		//			However, on connectionless sockets (UDP) only if they 
		//			have a stipulated default peer address established through 
		//			the connect or WSAConnect function.
		//

		if (this->m_bTcp)
		{
			//	If this is a TCP
			nError = WSASend(this->m_Socket, 
							(LPWSABUF)&sNetBuffer, 
							1, 
							&dwBytesSent, 
							0,
							(WSAOVERLAPPED *)&this->m_WriteOverlapped, 
							NULL);
		}
		else
		{
			//	If this is a UDP
			nError = WSASendTo(this->m_Socket,
							(LPWSABUF)&sNetBuffer, 
							1, 
							&dwBytesSent, 
							0,
							(LPSOCKADDR)&m_sSocketAddress,
							m_nSocketAddressSize,
							(WSAOVERLAPPED *)&this->m_WriteOverlapped, 
							NULL);
		}

		if (ERROR_SUCCESS == nError)
		{
			dwErrorCode = IO_SUCCESS;
			// calculate what's left to send 
			dwBytesTotalSent += dwBytesSent;
			dwBytesLeftToSend = dwSize - dwBytesTotalSent;
		}
		else if (nError == SOCKET_ERROR)
		{

			nError = WSAGetLastError();

			switch (nError)
			{
				//	A successful WSAStartup must occour
				case WSANOTINITIALISED	:	
					sprintf(szMsg, "Send Error %ud Successful startup not occoured for Ip Address %s", nError, this->m_szIpAddress);
					DisplayMessage(szMsg);
					this->Close();
					this->Open();
					break;

				//	The network subsystem has failed
				case WSAENETDOWN		:
					sprintf(szMsg, "Send Error %ud Network Sub-system failed for Ip Address %s", nError, this->m_szIpAddress);
					DisplayMessage(szMsg);
					this->Close();

⌨️ 快捷键说明

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