windows C++ tcp 广播接收端

头文件:

#ifndef __MANAGE_NET__
#define __MANAGE_NET__

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

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

	bool SetFunc(const std::function<void(const char*, long)>& func);
	bool Init(long nPort);
    bool Write(unsigned char* pData, long nSize);
    void Uninit();
    
private:
	bool Connect(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:
    long m_nPort;
    
private:
    SOCKET sClient;

private:
	SOCKADDR_IN m_clientAddr;
};

#endif

源文件:

#include "BroadcastClient.h"

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

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

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

bool BroadcastClient::SetFunc(const std::function<void(const char*, long)>& pFunc)
{
	if (pFunc){
		m_pFunc = pFunc;
		return true;
	}
	return false;
}
bool BroadcastClient::Connect(long nPort)
{
	sClient = socket(AF_INET, SOCK_DGRAM, 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 = htonl(INADDR_ANY);//IP地址
	if (::bind(sClient, (SOCKADDR*)&seraddr, sizeof(seraddr)) != 0){
		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 BroadcastClient::Init(long nPort)
{ 
	bool bRet = Connect(nPort);
	if (bRet){
		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 BroadcastClient::Read(unsigned char* pData, long nSize)
{
    if(sClient != INVALID_SOCKET){
		int addrLen = sizeof(m_clientAddr);
		return recvfrom(sClient, (char*)pData, nSize, 0, (SOCKADDR*)&m_clientAddr, &addrLen);
    }
    
	return 0;
}
bool BroadcastClient::Write(unsigned char* pData, long nSize)
{
	int addrLen = sizeof(m_clientAddr);
    long nLen = sendto(sClient, (char*)pData, nSize, 0, (SOCKADDR*)&m_clientAddr, addrLen);
    if(nLen == SOCKET_ERROR){
        return false;
    }
    return true;
}
void BroadcastClient::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 BroadcastClient::DisConnect()
{
	closesocket(sClient);
	sClient = INVALID_SOCKET;
}

unsigned int BroadcastClient::Process(void* args)
{
	BroadcastClient* pThis = (BroadcastClient*)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_nPort);
			}
			else if (nRet == SOCKET_ERROR){
				if (WSAGetLastError() != WSAETIMEDOUT){
					pThis->DisConnect();
					pThis->Connect(pThis->m_nPort);
				}
			}
		}
	}

	return 0;
}

调用:

BroadcastClient::GetInstance()->SetFunc(&ManageNetCB::ProcessNet);
BroadcastClient::GetInstance()->Init(8001);

char cData[2048] = {0};
sprintf(cData, "cmd=ReportStudentName_req&data=%s\n", UNICODE_TO_ANSI(wcData).c_str());
BroadcastClient::GetInstance()->Write((unsigned char*)cData, strlen(cData));

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值