#pragma once
/********************************************************************
创建时间: 2016/04/12
文件名称: BroadcastMsg.h
创建人: wanglong
功能描述: 广播发送消息类
使用步骤: 1> 初始化SOCKET InitSocket
2> 发送消息 SendMsg
3> 设置接受消息回调函数 SetRecvMsgProc
4> 释放资源 ReleaseRes
修改历史: 10:4:2015 17:18 |wanglong 添加功能描述
*********************************************************************/
typedef struct tagRecvMsg
{
void* pVOID;
LPCSTR lpMsg;
}RECVMSG;
typedef void (_stdcall *RECVMSGPROC) (const RECVMSG& recvMsg);
class CBroadcastMsg
{
public:
CBroadcastMsg(void);
~CBroadcastMsg(void);
public:
//初始化SOCKET
BOOL InitSocket();
//释放资源
void ReleaseRes();
//设置接受消息回调函数
void SetRecvMsgProc(VOID* pVOID,RECVMSGPROC recvMsgProc);
//发送消息
void SendMsg(LPCSTR lpMsg);
private:
//接受线程消息
static unsigned __stdcall RecvMsgProc(LPVOID lpParam);
//
void OnRecvMsg();
private:
RECVMSGPROC m_recvMsgProc;
RECVMSG m_recvMsg;
BOOL m_bRunning;
HANDLE m_hExeEvent[3]; //0 线程句柄 1 退出线程通知 2 有数据可读
SOCKET m_sendSocket;
SOCKET m_recvSocket;
};
.cpp文件
#include "StdAfx.h"
#include "BroadcastMsg.h"
#define SOCKET_PORT 4567
CBroadcastMsg::CBroadcastMsg(void)
:m_recvMsgProc(NULL)
,m_bRunning(TRUE)
{
}
CBroadcastMsg::~CBroadcastMsg(void)
{
}
BOOL CBroadcastMsg::InitSocket()
{
//初始化socket
WSAData wsaData;
int err;
err = WSAStartup(MAKEWORD(2,2),&wsaData);
if(err!=0)
{
//OutputStringToDebugView(_T("could not find a usable Winsock.dll\r\n"));
return FALSE;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
//OutputStringToDebugView(_T("winsock.dll version must 2.0\r\n"));
WSACleanup( );
return FALSE;
}
//创建发送socket
m_sendSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
//设置广播
BOOL bBroadcast = TRUE;
::setsockopt(m_sendSocket, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL));
//创建接受socket
m_recvSocket = ::socket(AF_INET, SOCK_DGRAM, 0);
bBroadcast = TRUE;
::setsockopt(m_recvSocket, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL));
SOCKADDR_IN sin;
sin.sin_family = AF_INET;
sin.sin_port = ::htons(SOCKET_PORT);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(m_recvSocket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
{
DWORD DW = ::GetLastError();
return FALSE;
}
//设置接受、发送缓冲区
int SndBuf,RcvBuf,nSndBuf,nRcvBuf;
nSndBuf=sizeof(SndBuf);
nRcvBuf=sizeof(RcvBuf);
SndBuf=65536;
RcvBuf=65536;
setsockopt(m_sendSocket,SOL_SOCKET,SO_SNDBUF,(char*)&SndBuf,sizeof(SndBuf));
setsockopt(m_recvSocket,SOL_SOCKET,SO_RCVBUF,(char*)&RcvBuf,sizeof(RcvBuf));
getsockopt(m_recvSocket,SOL_SOCKET,SO_RCVBUF,(char*)&RcvBuf,&nRcvBuf);
getsockopt(m_sendSocket,SOL_SOCKET,SO_SNDBUF,(char*)&SndBuf,&nSndBuf);
//使用事件模型
m_hExeEvent[1] = CreateEvent(NULL,FALSE,FALSE,NULL);
m_hExeEvent[2] = WSACreateEvent();
WSAEventSelect(m_recvSocket,m_hExeEvent[2],FD_READ | FD_WRITE |FD_CONNECT | FD_CLOSE);
//线程接受数据
unsigned int dwThread;
m_hExeEvent[0] = (HANDLE)_beginthreadex(NULL,0,RecvMsgProc,(LPVOID)this,0,&dwThread);
return TRUE;
}
void CBroadcastMsg::ReleaseRes()
{
m_bRunning = FALSE;
//发送关闭线程信号
if( m_hExeEvent[1] )
SetEvent(m_hExeEvent[1]) ;
if( m_hExeEvent[0] )
WaitForSingleObject(m_hExeEvent[0] ,INFINITE);
for(int j = 0; j < 3; j++)
{
if( m_hExeEvent[j] )
{
CloseHandle( m_hExeEvent[j] ) ;
m_hExeEvent[j] = NULL ;
}
}
//
WSACleanup();
}
void CBroadcastMsg::SetRecvMsgProc( VOID* pVOID, RECVMSGPROC recvMsgProc )
{
m_recvMsgProc = recvMsgProc;
m_recvMsg.pVOID = pVOID;
}
void CBroadcastMsg::SendMsg( LPCSTR lpMsg )
{
if (lpMsg)
{
//设置广播地址
SOCKADDR_IN bcast;
bcast.sin_family = AF_INET;
bcast.sin_port = htons(SOCKET_PORT);
bcast.sin_addr.S_un.S_addr = INADDR_BROADCAST;
::sendto(m_sendSocket, lpMsg, strlen(lpMsg), 0, (sockaddr*)&bcast, sizeof(bcast));
}
}
unsigned __stdcall CBroadcastMsg::RecvMsgProc( LPVOID lpParam )
{
CBroadcastMsg* pThis = (CBroadcastMsg*)lpParam;
while(pThis->m_bRunning)
{
DWORD dwWait = ::WSAWaitForMultipleEvents(3,pThis->m_hExeEvent,FALSE,WSA_INFINITE,FALSE) - WSA_WAIT_EVENT_0;
switch(dwWait)
{
case 2: //read
{
WSANETWORKEVENTS NetworkEvents;
WSAEnumNetworkEvents(pThis->m_recvSocket,pThis->m_hExeEvent[2],&NetworkEvents);
if(NetworkEvents.lNetworkEvents & FD_CONNECT)
{
}
if(NetworkEvents.lNetworkEvents & FD_READ)
{
pThis->OnRecvMsg();
}
if(NetworkEvents.lNetworkEvents & FD_WRITE)
{
}
if(NetworkEvents.lNetworkEvents & FD_CLOSE)
{
}
}
break;
case 1: //
break;
case WSA_WAIT_FAILED:
break;
}
}
return 1;
}
void CBroadcastMsg::OnRecvMsg()
{
char sz[1024] = {0};
SOCKADDR_IN addrRemote;
int nLen = sizeof(SOCKADDR_IN);
/*while (1) //大量数据,要考虑多次接收
{ */
int nRet = ::recvfrom(m_recvSocket, sz, sizeof(sz), 0, (sockaddr*)&addrRemote, &nLen);
if (nRet > 0)
{
sz[nRet] = '\0';
if (m_recvMsgProc)
{
m_recvMsg.lpMsg = sz;
m_recvMsgProc(m_recvMsg);
}
}
/* break;
} */
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wclaccp/article/details/51134224