mfc实现TCP通信

#include "stdafx.h"
#include "TCP.h"
#include "CDV.h"

void Task(LPVOID param)
{
	CTCP * pTcp = (CTCP *)param;
	//while (pTcp->Recv()>=0);

}

CTCP::CTCP()
{
	m_connectSocket = INVALID_SOCKET;
}


CTCP::~CTCP()
{
	CloseConnect();
}

CTCP::CTCP(PCSTR ip, PCSTR port)
{
	m_ip = ip;
	m_port = port;
	m_connectSocket = INVALID_SOCKET;
	if (ConnectServer(ip, port));
}

void CTCP::StartTask()
{
	_beginthread(Task, 0, this);
}
//-1失败
int CTCP::ConnectServer(PCSTR ip, PCSTR port, bool notice)
{
	CloseConnect();

	m_ip = ip;
	m_port = port;

	WSADATA wsaData;

	struct addrinfo *result = NULL,
		*ptr = NULL,
		hints;

	int iResult;

	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		if (notice)
			::AfxMessageBox(_T("网络连接失败"), MB_ICONWARNING, TRUE);
		return -1;
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	// Resolve the server address and port
	iResult = getaddrinfo(ip, port, &hints, &result);
	if (iResult != 0) {
		WSACleanup();
		if (notice)
			::AfxMessageBox(_T("网络连接失败"), MB_ICONWARNING, TRUE);
		return -1;
	}

	// Attempt to connect to an address until one succeeds
	for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

		// Create a SOCKET for connecting to server
		m_connectSocket = socket(ptr->ai_family, ptr->ai_socktype,
			ptr->ai_protocol);
		if (m_connectSocket == INVALID_SOCKET) {
			WSACleanup();
			if (notice)
				::AfxMessageBox(_T("网络连接失败"), MB_ICONWARNING, TRUE);
			return -1;
		}

		int iMode = 1;
		ioctlsocket(m_connectSocket, FIONBIO, (u_long FAR*)&iMode);
		// Connect to server.
		iResult = connect(m_connectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);

		struct timeval tm;
		tm.tv_sec = 5;
		tm.tv_usec = 0;
		int ret = -1;


		// 尝试去连接服务端  
		if (-1 != iResult)
		{
			ret = 1; // 连接成功  
		}
		else
		{
			fd_set set;
			FD_ZERO(&set);
			FD_SET(m_connectSocket, &set);

			int sel = select(-1, NULL, &set, NULL, &tm);
			if (sel <= 0)
			{
				ret = -1; // 有错误
			}
			else if (FD_ISSET(m_connectSocket, &set))
			{
				int error = -1;
				int optLen = sizeof(int);
				int get = getsockopt(m_connectSocket, SOL_SOCKET, SO_ERROR, (char*)&error, &optLen);

				if (0 != error)
				{
					ret = -1; // 有错误  
				}
				else
				{
					ret = 1;  // 无错误  
				}
			}

		}

		iMode = 0;
		ioctlsocket(m_connectSocket, FIONBIO, (u_long FAR*)&iMode);

		if (-1 == ret) {
			closesocket(m_connectSocket);
			m_connectSocket = INVALID_SOCKET;
		}

	}

	freeaddrinfo(result);

	char tbuf[10] = "hello";
	//int ret = Send(tbuf, 5);
	int ret = Recv(tbuf, 10, 10);

	if (-1 == ret || m_connectSocket == INVALID_SOCKET) {
		WSACleanup();
		if (notice)
		{
			GGStop = -1;//2670 打开NPC项目,显示网络连接失败,打开某一个路径后,右下角显示网络状态已连接,大概3秒之后会显示网络未连接(实际状态未连接)
			//::AfxMessageBox(_T("网络连接失败"), MB_ICONWARNING, TRUE);
		}
		return -1;
	}
	if (notice)
	{
		GGStop = 1;
		//::AfxMessageBox(_T("恭喜,网络连接成功!"), MB_ICONWARNING, TRUE);
	}
	return 0;
}

int CTCP::ConnectServer(CString ip, UINT port)
{
	CString csPort;
	csPort.Format("%d", port);
	int ret = ConnectServer(ip.GetBuffer(), csPort.GetBuffer());
	ip.ReleaseBuffer();
	csPort.ReleaseBuffer();
	return ret;
}


int CTCP::ConnectServer(CString ip, CString port, bool notice)
{
	if (!notice)
	{
		int ret = ConnectServer(ip.GetBuffer(), port.GetBuffer(),false);
		ip.ReleaseBuffer();
		port.ReleaseBuffer();
		return ret;
	}
}


int CTCP::CloseConnect()
{
	if (m_connectSocket == INVALID_SOCKET)
		return 0;
	// shutdown the connection since no more data will be sent
	int iResult = shutdown(m_connectSocket, SD_SEND);
	if (iResult == SOCKET_ERROR) {
		closesocket(m_connectSocket);
		WSACleanup();
		return -1;
	}

	// Receive until the peer closes the connection
	/*int timeout = 100;
	int ret = setsockopt(m_connectSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

	do {
	  char recvbuf[100];
	  iResult = recv(m_connectSocket, recvbuf, 100, 0);
	} while (iResult > 0);*/
	Clean();

	// cleanup
	closesocket(m_connectSocket);
	WSACleanup();
	return 0;
}

//-1连接出错close
int CTCP::Send(char * buf, int len)
{
	int step = 250;
	int delay = 5;
	int iResult;
	int i = 0;
	if (m_connectSocket == INVALID_SOCKET)
		return -1;
	int senBuflen;
	/*  int size = sizeof(senBuflen);
	  int ret = getsockopt(m_connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&senBuflen, &size);
	  senBuflen = len;// 0x10000;
	  ret = setsockopt(m_connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&senBuflen, size);

	  ret = getsockopt(m_connectSocket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*)&senBuflen, &size);
	*/

	//for (i = 0; i < len; ) {
	//  if (i + step <= len)
	//  {

	//  }
	//  else
	//  {
	//    step = len - i;
	//  }
	//  iResult = send(m_connectSocket, buf + i, step, 0);
	//  if (iResult < step) {
	//    int error = WSAGetLastError();
	//    if (iResult == SOCKET_ERROR) {
	//      return -1;
	//    }
	//    else
	//    {
	//      i += iResult;
	//    }
	//  }
	//  else if(iResult == step)
	//  {
	//    i += step;
	//  }
	//  else
	//  {

	//  }

	//  //Sleep(delay);
	//}
	iResult = send(m_connectSocket, buf, len, 0);
	return 0;
}

//返回接收长度
//-1连接出错close
int CTCP::Recv(char * buf, int len, int timeout)
{
	if (m_connectSocket == INVALID_SOCKET)
		return -1;
	// Receive until the peer closes the connection
	int ret = setsockopt(m_connectSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
	int iResult;
	int rlen = 0;

	/*while (rlen < len)
	{*/
	iResult = recv(m_connectSocket, buf + rlen, len, 0);

	int error = WSAGetLastError();
	if (iResult > 0)
	{
		rlen += iResult;
	}
	else if (WSAETIMEDOUT == error)
	{
		return 0;
	}
	else
	{
		return -1;
	}
	//}
	return rlen;
}


//返回接收长度
//-1连接出错close
int CTCP::Recv1(char * buf, int len, int timeout)
{
	if (m_connectSocket == INVALID_SOCKET)
		return -1;
	// Receive until the peer closes the connection
	int ret = setsockopt(m_connectSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
	int iResult;
	int rlen = 0;

	while (rlen < len)
	{
		iResult = recv(m_connectSocket, buf + rlen, len, 0);

		int error = WSAGetLastError();
		if (iResult > 0)
		{
			rlen += iResult;
		}
		else if (WSAETIMEDOUT == error)
		{
			return 0;
		}
		else
		{
			return -1;
		}
	}
	return rlen;
}

void CTCP::Clean()
{
	int iResult;
	int timeout = 1;
	int ret = setsockopt(m_connectSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

	do {
		char recvbuf[100];
		iResult = recv(m_connectSocket, recvbuf, 100, 0);
	} while (iResult > 0);

	return;
}

int CTCP::NPC_SendAndRecv(char * sbuf, int slen, char * rbuf, int rlen, bool *bcrc, int rTimeout, bool notice)
{
	ASSERT(sbuf && rbuf);
	int ret = 0;
	bool bret = false;
	unsigned short crc = 0;

	if (bcrc && slen)
	{
		crc = getCRC16(sbuf, slen);
		char temp1 = crc & 0xff;
		char temp0 = (crc >> 8) & 0xff;
		sbuf[slen] = temp1;
		sbuf[slen + 1] = temp0;
		slen += 2;
	}

	Clean();

	if (slen)
		ret = Send(sbuf, slen);

	if (-1 < ret)
		ret = Recv(rbuf, rlen, rTimeout);

	if (ret > -1)
	{
		if (ret > 2 && bcrc)
		{
			crc = getCRC16(rbuf, ret - 2);
			if (((char)(crc & 0xff) == rbuf[ret - 2]) && ((char)((crc >> 8) & 0xff) == rbuf[ret - 1]))
			{
				bret = true;
			}
			else
			{
				bret = false;
			}
		}
	}
	else
	{
		if (!notice /*|| IDOK == AfxMessageBox(_T("发送接收失败,是否尝试连接!"), MB_OKCANCEL, TRUE)*/)
		{
			ConnectServer(m_ip, m_port, false);
		}
	}

	if (bcrc)
		*bcrc = bret;

	return ret;
}



int CTCP::NPC_Recv(char * rbuf, int rlen, bool *bcrc, int rTimeout, bool notice)
{
	int ret = 0;            //5.20 原不注释
	bool bret = false;
	unsigned short crc = 0;

	//5.20
	//int ret = 0;
	//bool bret = false;
	//unsigned short crc = 0;
	//if (bcrc && rlen)
	//{
	//	crc = getCRC16(rbuf, rlen);
	//	char temp1 = crc & 0xff;
	//	char temp0 = (crc >> 8) & 0xff;
	//	rbuf[rlen] = temp1;
	//	rbuf[rlen + 1] = temp0;
	//	rlen += 2;
	//}

	Clean();

	ret = Recv1(rbuf, rlen, rTimeout);

	if (ret > -1)
	{
		if (ret > 2 && bcrc)
		{
			crc = getCRC16(rbuf, ret - 2);
			if (((char)(crc & 0xff) == rbuf[ret - 2]) && ((char)((crc >> 8) & 0xff) == rbuf[ret - 1]))
			{
				bret = true;
			}
			else
			{
				bret = false;
			}
		}
	}
	//else
	//{
	//	if (!notice /*|| IDOK == AfxMessageBox(_T("发送接收失败,是否尝试连接!"), MB_OKCANCEL, TRUE)*/)
	//	{
	//		ConnectServer(m_ip, m_port, false);
	//	}
	//}

	if (bcrc)
		*bcrc = bret;

	return ret;
}

你可能感兴趣的:(C++,mfc,mfc,tcp/ip,c++)