您的位置:首页 > 其它

局域网聊天,广播消息

2016-04-12 15:59 288 查看
本类可用来发送广播消息、局域网聊天

.h文件
#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博客,转载请标明出处:/article/10139871.html


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: