一个实现多播的类 - CMultiCast

用法:

CMultiCast cast("225.6.7.8", 7000);
cast.Startup();
cast.Send(...); //向组播发送数据包
cast.OnReceive(绑定回调函数);
cast.Listen(); //为数据接收启动监听
cast.ShutDown();


代码:
#ifndef WEISUNDING_MULTICAST
#define WEISUNDING_MULTICAST

#include 
#pragma comment(lib,"Ws2_32.lib") 
#define BUFFER_SIZE 65535

//-----------------------------------
//描述:一个实现多播的类
//作者:魏孙鼎
//日期:2005-8-1
//-----------------------------------
class CMultiCast
{
public:
    
	typedef void (*LPONRECEIVE)(const char* lpBuffer, int size);
	SOCKET	m_socket;
	bool	m_bContinue ;	//指示线程是否继续监听  

private:  

	sockaddr_in m_addrlocal;
	sockaddr_in m_addrgroup;  //多播IP地址结构
	const char* m_lpCastIP;
	const int   m_castPort; 	  	
	LPONRECEIVE m_lpOnReceive;  //回调函数指针
	HANDLE		m_hThread;	  //用于监听的线程
	

public:

	CMultiCast(const char* lpGroupIP, int port) : m_lpCastIP(lpGroupIP),
											      m_lpOnReceive(NULL),
												  m_hThread(NULL),
												  m_castPort(port),
												  m_bContinue(true)
	{
		WSADATA wsaData;
		if (WSAStartup(MAKEWORD(2, 2) , &wsaData) != 0 )
		{
			AfxMessageBox("初始化套接字错误");  	
			return;
		}		
	}

	void Send(const char* lpBuffer, int size)
	{
		sendto(m_socket, lpBuffer, size, NULL, (sockaddr*)&m_addrgroup, sizeof(sockaddr));			
	}

	//绑定数据接收事件
	void OnReceive(LPONRECEIVE lpCallBack)
	{
		m_lpOnReceive = lpCallBack;					
	}

	//为数据接收启动监听
	void Listen()
	{
		if (m_hThread != NULL )		
			return;

		m_bContinue = true;
		m_hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ListenProc, this, NULL, NULL);  
	}

	static int ListenProc(LPVOID lpParam)
	{
		
		CMultiCast* lpCast = (CMultiCast*)lpParam;
		char buffer[BUFFER_SIZE] = "/0";
		sockaddr addrFrom;
		int len = sizeof(addrFrom);
		int c = 0;

		while(lpCast->m_bContinue)
		{
			c = recvfrom(lpCast->m_socket, buffer, sizeof(buffer), 0 , &addrFrom, &len);  			
			
			if ( (lpCast->m_lpOnReceive != NULL) && (c > 0) )
			{
				//激发回调事件
				lpCast->m_lpOnReceive(buffer, c);	
			}			
		}
		
		return 0;
	}
    
	bool Startup()
	{
		int ret;
		m_socket = WSASocket(AF_INET, SOCK_DGRAM, NULL, NULL, NULL, WSA_FLAG_MULTIPOINT_C_LEAF |
																	WSA_FLAG_MULTIPOINT_D_LEAF | 
																	WSA_FLAG_OVERLAPPED);	

		共用端口
		const int on = 1; 
		ret = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); 

		m_addrlocal.sin_family = AF_INET;
		m_addrlocal.sin_port   = htons(m_castPort);
		m_addrlocal.sin_addr.S_un.S_addr = INADDR_ANY;

		//可以不用绑定
		if (bind(m_socket, (LPSOCKADDR)&m_addrlocal, sizeof(m_addrlocal)) == SOCKET_ERROR)
		{
			closesocket(m_socket);
			AfxMessageBox("初始化SOCKET错误,无法绑定IP地址");
			return false;
		}		 
		
		int m_OptVal = 1;
		int m_cbRet = 0;

		if ( WSAIoctl(m_socket, SIO_MULTICAST_SCOPE, &m_OptVal,
			sizeof (m_OptVal), NULL, NULL, (unsigned long*)&m_cbRet, NULL, NULL) == SOCKET_ERROR)
		{			
			closesocket(m_socket);
			AfxMessageBox("初始化SOCKET错误,无法设置TTL");
			return false;
		} 		

		m_addrgroup.sin_family = AF_INET;
		m_addrgroup.sin_port = htons(m_castPort);
		m_addrgroup.sin_addr.S_un.S_addr = inet_addr(m_lpCastIP);

		ret = WSAJoinLeaf(m_socket, (PSOCKADDR)&m_addrgroup,sizeof(sockaddr_in), NULL, NULL, NULL, NULL, JL_BOTH);	

		if (ret == INVALID_SOCKET)
		{
			closesocket(m_socket);
			AfxMessageBox("初始化SOCKET错误,无法加入多播组");
			return false;
		}	

		return true;
	}

	void ShutDown()
	{
		//关闭监听线程
		if (m_hThread != NULL )
		{
			m_bContinue = false;
			
			if (WaitForSingleObject( m_hThread, 500) != WAIT_OBJECT_0)
			{
				try
				{
					TerminateThread(m_hThread, 0);
				}
				catch(...)
				{
					
				}  
			}

			CloseHandle(m_hThread);
			m_hThread = NULL;
		}

		closesocket(m_socket);	
	}
    
	~CMultiCast()
	{
        ShutDown();		
	}
};

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值