用法:
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