本類可用來發送廣播消息、區域網路聊天
.h檔案
#pragma once
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 ) {
//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);
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);
}
}
}
本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/wclaccp/article/details/51134224