windows Tcp Client 自动重连封装

头文件:

#ifndef __MANAGE_NET__
#define __MANAGE_NET__

#include <vector>
#include <string>
#include <process.h>
#include <winsock2.h>
#include <functional>
using namespace std;

class ManageNet
{
public:
	ManageNet();
	~ManageNet();

public:
	static ManageNet* m_Instance;
	static ManageNet* GetInstance()
	{
		if (!m_Instance) {
			m_Instance = new ManageNet;
		}
		return m_Instance;
	}
	static void ReleaseInstance()
	{
		if (m_Instance) {
			delete m_Instance;
			m_Instance = NULL;
		}
	}

	bool SetFunc(const std::function<void(const char*, long)>&pFunc);
	bool Init(const char* pstrIP, long nPort);
	bool Write(unsigned char* pData, long nSize);
	void Uninit();

private:
	bool Connect(const char* pstrIP, long nPort);
	void DisConnect();
	long Read(unsigned char* pData, long nSize);
	static unsigned int __stdcall Process(void* args);

private:
	std::function<void(const char*, long)> m_pFunc;

private:
	HANDLE m_threadRecv;
	HANDLE m_threadEvent;

private:
	string m_strIP;
	long   m_nPort;

private:
	SOCKET sClient;
};

#endif

源文件:

#include "TcpClient.h"

#pragma warning(disable:4996)
#pragma comment(lib, "ws2_32.lib")

ManageNet* ManageNet::m_Instance = NULL;
ManageNet::ManageNet()
{
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2, 2), &wsadata);

	m_threadRecv = INVALID_HANDLE_VALUE;
	m_threadEvent = INVALID_HANDLE_VALUE;
}
ManageNet::~ManageNet()
{
	Uninit();
	WSACleanup();
}

bool ManageNet::SetFunc(const std::function<void(const char*, long)>& pFunc)
{
	if (pFunc) {
		m_pFunc = pFunc;
		return true;
	}
	return false;
}
bool ManageNet::Connect(const char* pstrIP, long nPort)
{
	sClient = socket(AF_INET, SOCK_STREAM, 0);
	if (sClient == INVALID_SOCKET) {
		return false;
	}

	struct sockaddr_in seraddr;
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(nPort);
	seraddr.sin_addr.S_un.S_addr = inet_addr(pstrIP);//IP地址
	if (connect(sClient, (const struct sockaddr*)&seraddr, sizeof(seraddr)) == SOCKET_ERROR) {
		DWORD dwErr = GetLastError();
		return false;
	}

	int nTimeout = 1000;//
	setsockopt(sClient, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeout, sizeof(int));
	setsockopt(sClient, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTimeout, sizeof(int));
	return true;
}
bool ManageNet::Init(const char* pstrIP, long nPort)
{
	if (!pstrIP) {
		return false;
	}

	bool bRet = Connect(pstrIP, nPort);
	if (bRet) {
		m_strIP = pstrIP;
		m_nPort = nPort;
		m_threadEvent = CreateEvent(NULL, true, false, L"");
		m_threadRecv = (HANDLE)_beginthreadex(NULL, 0, Process, this, 0, NULL);
		return true;
	}

	return false;
}
long ManageNet::Read(unsigned char* pData, long nSize)
{
	if (sClient != INVALID_SOCKET) {
		return recv(sClient, (char*)pData, nSize, 0);
	}

	return 0;
}
bool ManageNet::Write(unsigned char* pData, long nSize)
{
	long nLen = send(sClient, (char*)pData, nSize, 0);
	if (nLen == SOCKET_ERROR) {
		return false;
	}
	return true;
}
void ManageNet::Uninit()
{
	if (m_threadRecv != INVALID_HANDLE_VALUE && m_threadEvent != INVALID_HANDLE_VALUE) {
		SetEvent(m_threadEvent);
		WaitForSingleObject(m_threadRecv, INFINITE);
		CloseHandle(m_threadRecv);
		CloseHandle(m_threadEvent);

		m_threadRecv = INVALID_HANDLE_VALUE;
		m_threadEvent = INVALID_HANDLE_VALUE;
	}

	DisConnect();
}
void ManageNet::DisConnect()
{
	closesocket(sClient);
	sClient = INVALID_SOCKET;
}

unsigned int ManageNet::Process(void* args)
{
	ManageNet* pThis = (ManageNet*)args;

	while (true) {
		if (WaitForSingleObject(pThis->m_threadEvent, 10) == WAIT_OBJECT_0) {
			break;
		}
		char cData[2048] = { 0 };
		long nRet = pThis->Read((unsigned char*)cData, 2048);
		if (nRet > 0) {
			if (pThis->m_pFunc) {
				pThis->m_pFunc(cData, nRet);
			}
		}
		else {
			if (nRet == 0) {//不能在这里调用Uninit。因为会发生死锁
				pThis->DisConnect();
				pThis->Connect(pThis->m_strIP.c_str(), pThis->m_nPort);
			}
			else if (nRet == SOCKET_ERROR) {
				if (WSAGetLastError() != WSAETIMEDOUT) {
					pThis->DisConnect();
					pThis->Connect(pThis->m_strIP.c_str(), pThis->m_nPort);
				}
			}
		}
	}

	return 0;
}

调用:

ManageNet::GetInstance()->SetFunc(TcpDataOutputCB);
ManageNet::GetInstance()->Init("127.0.0.1", 8000);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值