C++ TCP连接方式(MFC版)

TCPSocket.h

#include <winsock2.h>

/*_____________________________TCP-Client_______________________________*/

class TcpClinet
{
    
    
public:
	TcpClinet();
	TcpClinet(const std::string& IP, int Port);
	~TcpClinet();
public:
	bool Connect(bool bMutex = false) override;
	void DisConnect(bool bMutex = false) override;
	bool clearBuf_c();
	bool recvBuf_c(char* pStr, int& len, int waitTimeMS = 0) override;
	bool sendBuf_c(char const *pStr, const int& len) override;
protected:
	bool Connect(std::string IP, int Port);
	bool isActive();
private:
	SOCKET m_socketClient;
};

/*__________________________TCP-Server__________________________________*/

class TcpServer
{
    
    
public:
	TcpServer();
	TcpServer(const std::string& IP, int Port);
	~TcpServer();
	
public:
	bool Connect(bool bMutex = false) override;
	void DisConnect(bool bMutex = false) override;
	bool clearBuf_c();
	bool recvBuf_c(char* pStr, int& len, int waitTimeMS = 0) override;
	bool sendBuf_c(char const *pStr, const int& len) override;
protected:
	bool ConnectClient();
	bool Connect(std::string IP, int Port);
private:
	bool m_ServerOK;
	SOCKET m_socketServer;
	SOCKET m_socketClient;
	std::list<SOCKET> m_socketClientList;
};

TCPSocket.cpp

/*_____________________________TCP-Client_______________________________*/

TcpClinet::TcpClinet(void)
{
    
    
	m_socketClient = SOCKET_ERROR;
	m_typeName = "TCP-客户端";
}

TcpClinet::TcpClinet(const std::string& IP, int Port)
	: ISocketBaese(IP, Port, SOCKET_TYPE_TCP_CLINET)
{
    
    
	m_socketClient = SOCKET_ERROR;
	m_typeName = "TCP-客户端";
}

TcpClinet::~TcpClinet(void)
{
    
    
}

bool TcpClinet::Connect(bool bMutex)
{
    
    
	if (bMutex)
	{
    
    
		QMutexLocker locker(&m_Mutex);
		return Connect(m_IP, m_Port);
	}
	return Connect(m_IP, m_Port);
}

bool TcpClinet::Connect(std::string IP, int Port)
{
    
    
	DisConnect();
	char strIp[1024];
	memset(strIp, '\0', 1024);
	memcpy(strIp, IP.c_str(), IP.length());

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVersionRequested, &wsaData);//该函数的功能是加载一个Winsocket库版本
	if (err != 0)
		return false;

	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
    
    
		DisConnect();
		return false;
	}
	m_socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (m_socketClient == INVALID_SOCKET)
	{
    
    
		DisConnect();
		return false;
	}
/*
	//设置发送/接收超时时间

	struct timeval tSendTimeOut = { 6,0 };            //发送超时时间6s
	struct timeval tRecvTimeOut = { 6,0 };            //接收超时时间6s
	struct timeval tConnectTimeOut = { 0,500000 };       //连接超时时间500ms

	if (SOCKET_ERROR == setsockopt(m_sclient, SOL_SOCKET, SO_SNDTIMEO, (char*)&tSendTimeOut, sizeof(tSendTimeOut)))
	{
		DisConnect();
		return false;
	}

	if (SOCKET_ERROR == setsockopt(m_sclient, SOL_SOCKET, SO_RCVTIMEO, (char*)&tRecvTimeOut, sizeof(tRecvTimeOut)))
	{
		DisConnect();
		return false;
	}

	//设置为不延时发送
	int v2 = 1;
	if (SOCKET_ERROR == setsockopt(m_sclient, IPPROTO_TCP, TCP_NODELAY, (const char*)&v2, sizeof(v2)))
	{
		DisConnect();
		return false;
	}
*/
	//设置为非阻塞模式
	u_long u1 = 1;
	if (SOCKET_ERROR == ioctlsocket(m_socketClient, FIONBIO, &u1))
	{
    
    
		DisConnect();
		return false;
	}

	SOCKADDR_IN addrSrv;
	memset((char*)&addrSrv, 0, sizeof(addrSrv));
	addrSrv.sin_addr.S_un.S_addr = inet_addr(strIp);	//设定需要连接的服务器的ip地址
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(Port);				//设定需要连接的服务器的端口地址
	//Sleep(500);
	bool bRet = false;
	int  nRet = 0;
	for (int nLoop = 0; nLoop < 2; nLoop++)
	{
    
    
		int iRtn = connect(m_socketClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
		if (iRtn == SOCKET_ERROR)
		{
    
    
			if (WSAEWOULDBLOCK != WSAGetLastError())//非阻塞 不能马上连上的,会返回这个状态
			{
    
    
				DisConnect();
				return false;
			}
		}

		//select超时时间设置
		fd_set fd;
		FD_ZERO(&fd);
		FD_SET(m_socketClient, &fd);
		struct timeval tConnectTimeOut = {
    
     0,500000 };       //连接超时时间500ms
		nRet = select(0, 0, &fd, 0, &tConnectTimeOut);

		if (nRet <= 0)
		{
    
    
			bRet = false;
			continue;
		}
		else
		{
    
    
			bRet = true;
			break;
		}
	}
	//连接失败
	if (!bRet)
	{
    
    
		DisConnect();
		return false;
	}
	m_bConnectOK = true;
	//if (m_ConnectChangeFun)
	//	(*m_ConnectChangeFun)(m_bConnectOK);
	return true;
}

bool TcpClinet::isActive()
{
    
    
	int opt_val;
	socklen_t opt_len = sizeof(opt_val);
	int error = -1, len2;
	len2 = sizeof(int);
	int r = getsockopt(m_socketClient, SOL_SOCKET, SO_KEEPALIVE, (char*)&error, &len2);
	if (r != 0 || error == -1)
	{
    
    
		if (!Connect())
		{
    
    
			return false;
		}
	}
	return true;
}

void TcpClinet::DisConnect(bool bMutex)
{
    
    
	if (m_socketClient != SOCKET_ERROR)
	{
    
    
		closesocket(m_socketClient);
		//WSACleanup();
	}

	m_bConnectOK = false;
	m_socketClient = SOCKET_ERROR;
	//if (m_ConnectChangeFun)
	//	(*m_ConnectChangeFun)(m_bConnectOK);
}

bool TcpClinet::clearBuf_c()
{
    
    
	DWORD initTime = GetTickCount();
	do
	{
    
    
		if (0 <= recv(m_socketClient, m_recvBuffer, CHAR_LEN, 0))
			return true;
		if (abs(int(GetTickCount() - initTime)) > 1000)
			return false;
	} while (1);
	return false;
}

bool TcpClinet::recvBuf_c(char* pStr, int& len, int waitTimeMS)
{
    
    
	QMutexLocker locker(&m_Mutex);
	if (!isActive())
		return false;
	memset(m_recvBuffer, '\0', CHAR_LEN);
	int buflen;
	DWORD initTime = GetTickCount();
	while (true)
	{
    
    
		buflen = recv(m_socketClient, m_recvBuffer, CHAR_LEN, 0);
		if (buflen > 0)
		{
    
    
			memcpy(pStr, m_recvBuffer, buflen);
			len = buflen;
			return true;
		}
		//当接受数据时断开连接会返回0
		else if (buflen == 0)
		{
    
    
			Connect();
			return false;
		}
		//初始等待连接或是已连接未收到数据返回-1
		else if (buflen < 0)
		{
    
    
			if (!m_bConnectOK)
				Connect();
			if (abs(int(GetTickCount() - initTime)) > waitTimeMS)
				return false;
		}
	}
	return true;
}

bool TcpClinet::sendBuf_c(char const *pStr, const int& len)
{
    
    
	QMutexLocker locker(&m_Mutex);
	if (!isActive())
		return false;
	int rtn = send(m_socketClient, pStr, len, 0);
	if (rtn < 0)
	{
    
    
		Connect();
		return false;
	}
	return true;
}

/*__________________________TCP-Server__________________________________*/

TcpServer::TcpServer(void)
{
    
    
	m_socketServer = SOCKET_ERROR;
	m_socketClient = SOCKET_ERROR;
	m_ServerOK = false;
	m_typeName = "TCP-服务器";
}

TcpServer::TcpServer(const std::string& IP, int Port)
	: ISocketBaese(IP, Port, SOCKET_TYPE_TCP_SERVER)
{
    
    
	m_socketServer = SOCKET_ERROR;
	m_socketClient = SOCKET_ERROR;
	m_ServerOK = false;
	m_typeName = "TCP-服务器";
}

TcpServer::~TcpServer(void)
{
    
    
}

bool TcpServer::Connect(bool bMutex)
{
    
    
	if (bMutex)
	{
    
    
		QMutexLocker locker(&m_Mutex);
		if (m_ServerOK)
			return ConnectClient();
		return Connect(m_IP, m_Port);
	}
	if (m_ServerOK)
		return ConnectClient();
	return Connect(m_IP, m_Port);
}

bool TcpServer::ConnectClient()
{
    
    
	SOCKADDR_IN addrClt;
	int len = sizeof(SOCKADDR_IN);
	SOCKET socket = accept(m_socketServer, (SOCKADDR*)&addrClt, &len);
	if (socket != SOCKET_ERROR)
	{
    
    
		m_socketClient = socket;
		m_bConnectOK = true;
		m_socketClientList.push_back(socket);
		return true;
	}
	return false;
}

bool TcpServer::Connect(std::string IP, int Port)
{
    
    
	DisConnect();
	char strIp[1024];
	memset(strIp, '\0', 1024);
	memcpy(strIp, IP.c_str(), IP.length());

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVersionRequested, &wsaData);//该函数的功能是加载一个Winsocket库版本
	if (err != 0)
		return false;

	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
    
    
		DisConnect();
		return false;
	}
	m_socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (m_socketServer == INVALID_SOCKET)
	{
    
    
		DisConnect();
		return false;
	}
	//设置为非阻塞模式
	u_long u1 = 1;
	if (SOCKET_ERROR == ioctlsocket(m_socketServer, FIONBIO, &u1))
	{
    
    
		DisConnect();
		return false;
	}
	SOCKADDR_IN addrSrv;
	memset((char*)&addrSrv, 0, sizeof(addrSrv));
	addrSrv.sin_addr.S_un.S_addr = inet_addr(strIp);	//设定需要连接的服务器的ip地址
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(Port);				//设定需要连接的服务器的端口地址
	//Sleep(500);
	bool bRet = false;
	int  nRet = 0;
	int iRtn = bind(m_socketServer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
	if (iRtn == SOCKET_ERROR)
	{
    
    
		if (WSAEWOULDBLOCK != WSAGetLastError())//非阻塞 不能马上连上的,会返回这个状态
		{
    
    
			DisConnect();
			return false;
		}
	}
	//监听
	if (SOCKET_ERROR == listen(m_socketServer, 1))
	{
    
    
		DisConnect();
		return false;
	}
	m_ServerOK = true;
	return ConnectClient();
}

void TcpServer::DisConnect(bool bMutex)
{
    
    
	for (auto& it : m_socketClientList)
	{
    
    
		closesocket(it);
	}
	m_socketClientList.clear();
	if (m_socketServer != SOCKET_ERROR)
		closesocket(m_socketServer);
	//WSACleanup();
	m_socketServer = SOCKET_ERROR;
	m_socketClient = SOCKET_ERROR;
	m_bConnectOK = false;
	m_ServerOK = false;
}

bool TcpServer::clearBuf_c()
{
    
    
	DWORD initTime = GetTickCount();
	do
	{
    
    
		bool falg = 0;
		for (auto&it : m_socketClientList)
		{
    
    
			if (0 > recv(it, m_recvBuffer, CHAR_LEN, 0))
				falg = 1;
		}
		if (falg == 0) return true;
		if (abs(int(GetTickCount() - initTime)) > 1000)
			return false;
	} while (1);
	return false;
}

bool TcpServer::recvBuf_c(char* pStr, int& len, int waitTimeMS)
{
    
    
	QMutexLocker locker(&m_Mutex);
	memset(m_recvBuffer, '\0', CHAR_LEN);
	int buflen;
	DWORD initTime = GetTickCount();
	while (true)
	{
    
    
		for (auto&it : m_socketClientList)
		{
    
    
			m_socketClient = it;
			buflen = recv(m_socketClient, m_recvBuffer, CHAR_LEN, 0);
			if (buflen > 0)
			{
    
    
				memcpy(pStr, m_recvBuffer, buflen);
				len = buflen;
				return true;
			}
			//当接受数据时断开连接会返回0
			else if (buflen == 0)
			{
    
    
				m_socketClientList.remove(it);
				if (m_socketClientList.size() == 0)
				{
    
    
					m_socketClient = SOCKET_ERROR;
					m_bConnectOK = false;
				}
				Connect();
				return false;
			}
			//初始等待连接或是已连接未收到数据返回-1
			else if (buflen < 0)
			{
    
    
				Connect();
				if (abs(int(GetTickCount() - initTime)) > waitTimeMS)
					return false;
			}
		}
	}
	
	return true;
}

bool TcpServer::sendBuf_c(char const *pStr, const int& len)
{
    
    
	QMutexLocker locker(&m_Mutex);
	memset(m_sendBuffer, '\0', CHAR_LEN);
	memcpy(m_sendBuffer, pStr, len);
	int rtn = send(m_socketClient, m_sendBuffer, len, 0);
	if (rtn < 0)
	{
    
    
		Connect();
		return false;
	}
	return true;
}

猜你喜欢

转载自blog.csdn.net/Liang_ming_/article/details/131667363