boost库之udp广播实例
//UdpLinkServer.h
//udp服务 #pragma once #include <boost/asio/ip/tcp.hpp> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/shared_ptr.hpp> #include <boost/array.hpp> #include <boost/function.hpp> using boost::asio::ip::udp; #define UDP_DATA_PACKAGE_MAX_LENGTH 1024 //发送数据回调函数 typedef void (CALLBACK *SendDataCallback)(const boost::system::error_code& error,std::size_t bytes_transferred,DWORD dwUserData1,DWORD dwUserData2); //接收数据回调函数 typedef void (CALLBACK *RecvDataCallback)(const boost::system::error_code& error,char *pData,int nDataLength,char *pPeerIp,unsigned short usPeerPort,DWORD dwUserData1,DWORD dwUserData2); class UdpLinkServer { public: UdpLinkServer(unsigned short usPort,bool bBroadcast); virtual ~UdpLinkServer(void); //发送数据回调函数 boost function定义 typedef boost::function<void* (const boost::system::error_code& error,std::size_t bytes_transferred,DWORD dwUserData1,DWORD dwUserData2)> SendDataCallbackHandler; /* 功能:设置接收数据回调函数 参数:bAutoRecvData:是否自动接收数据;pfunc:接收数据回调函数;dwUserData1:接收数据回调函数用户数据1;dwUserData2:接收数据回调函数用户数据2 返回值:无 */ void SetRecvDataCallback(bool bAutoRecvData,RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2); //开始 int Start(boost::asio::io_service& ioService); //停止 int Stop(); //发送数据 int SendDataEx(udp::endpoint endpointRemote,char *pBuffer,int nBufferSize,SendDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2); //发送数据 int SendData(char *pBuffer,int nBufferSize,bool bAsync); //获取广播端点 udp::endpoint & GetBroadcastEndPoint(); //接收数据处理(手动) void handleRecvDataByManual(RecvDataCallback pfunc=NULL,DWORD dwUserData1=0,DWORD dwUserData2=0); //当发送数据给客户端成功之后响应处理 void handleSendData(char *pBuffer,int nBufferSize,const boost::system::error_code& error,std::size_t bytes_transferred); void handleSendDataInner(SendDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2,const boost::system::error_code& error,std::size_t bytes_transferred); //void handleSendData(boost::shared_ptr<std::string> strMessage,const boost::system::error_code& error,std::size_t bytes_transferred); static void WINAPI SendDataCallbackOuter(const boost::system::error_code& error,std::size_t bytes_transferred,DWORD dwUserData1,DWORD dwUserData2); protected: //接收数据 void RecvDataProcess(RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2); //接收数据处理(自动) void handleRecvData(const boost::system::error_code& error,std::size_t bytes_transferred,RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2); //是否停止服务 bool IsStop(); private: udp::socket *m_sockUdp; //服务器的SOCKET udp::endpoint m_endpointRemote; //收到数据时的端点信息 udp::endpoint m_endpointBroadcast; //广播端点信息 boost::array<char,UDP_DATA_PACKAGE_MAX_LENGTH> m_recvBuf; //接收数据缓冲区 bool m_bStop; //停止服务 bool m_bBroadcast; //是否广播 unsigned short m_usPort; //端口 bool m_bAutoRecvData; //是否自动接收数据,true,表示自动接收数据;false,表示外部手动调用函数接收数据 RecvDataCallback m_pfuncRecvDataCallback; //接收数据回调函数 DWORD m_dwRecvDataCallbackUserData1; //接收数据回调函数用户数据1 DWORD m_dwRecvDataCallbackUserData2; //接收数据回调函数用户数据2 };
#include "StdAfx.h" #include "UdpLinkServer.h" #include <boost/exception/all.hpp> UdpLinkServer::UdpLinkServer(unsigned short usPort,bool bBroadcast) { m_bStop = false; m_bBroadcast = bBroadcast; m_usPort = usPort; m_sockUdp = NULL; m_bAutoRecvData = true; m_pfuncRecvDataCallback = NULL; m_dwRecvDataCallbackUserData1 = 0; m_dwRecvDataCallbackUserData2 = 0; } UdpLinkServer::~UdpLinkServer(void) { if(m_sockUdp != NULL) { m_sockUdp->close(); delete m_sockUdp; m_sockUdp = NULL; } } //设置接收数据回调函数 void UdpLinkServer::SetRecvDataCallback(bool bAutoRecvData,RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2) { m_bAutoRecvData = bAutoRecvData; m_pfuncRecvDataCallback = pfunc; m_dwRecvDataCallbackUserData1 = dwUserData1; m_dwRecvDataCallbackUserData2 = dwUserData2; } //开始 int UdpLinkServer::Start(boost::asio::io_service& ioService) { try { if(m_bBroadcast) { //广播 m_sockUdp = new udp::socket(ioService,udp::endpoint(udp::v4(),0)); m_sockUdp->set_option(boost::asio::socket_base::reuse_address(true)); m_sockUdp->set_option(boost::asio::socket_base::broadcast(true)); m_endpointBroadcast = udp::endpoint(boost::asio::ip::address_v4::broadcast(), m_usPort); } else { m_sockUdp = new udp::socket(ioService,udp::endpoint(udp::v4(),m_usPort)); if(!m_sockUdp->is_open()) { //端口被占用 return -1; } m_sockUdp->set_option(boost::asio::socket_base::reuse_address(true)); } } catch (boost::exception& e) { return -1; } m_bStop = false; if(m_bAutoRecvData) { RecvDataProcess(m_pfuncRecvDataCallback,m_dwRecvDataCallbackUserData1,m_dwRecvDataCallbackUserData2); } return 0; } //停止 int UdpLinkServer::Stop() { m_bStop = true; return 0; } //是否停止服务 bool UdpLinkServer::IsStop() { return m_bStop; } //获取广播端点 udp::endpoint & UdpLinkServer::GetBroadcastEndPoint() { return m_endpointBroadcast; } void UdpLinkServer::SendDataCallbackOuter(const boost::system::error_code& error,std::size_t bytes_transferred,DWORD dwUserData1,DWORD dwUserData2) { int i = 0; } //发送数据 int UdpLinkServer::SendDataEx(udp::endpoint endpointRemote,char *pBuffer,int nBufferSize,SendDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2) { m_sockUdp->async_send_to(boost::asio::buffer(pBuffer,nBufferSize),endpointRemote,boost::bind(&UdpLinkServer::handleSendDataInner,this,pfunc,dwUserData1,dwUserData2,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred)); return 0; } //发送数据 int UdpLinkServer::SendData(char *pBuffer,int nBufferSize,bool bAsync) { if(!m_bBroadcast) { if(bAsync) { //异步发送 m_sockUdp->async_send_to(boost::asio::buffer(pBuffer,nBufferSize),m_endpointRemote,boost::bind(&UdpLinkServer::handleSendData,this,pBuffer,nBufferSize,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred)); } else { //同步发送 m_sockUdp->send_to(boost::asio::buffer(pBuffer,nBufferSize),m_endpointRemote); } } else { //广播 if(bAsync) { //异步发送 m_sockUdp->async_send_to(boost::asio::buffer(pBuffer,nBufferSize),m_endpointBroadcast,boost::bind(&UdpLinkServer::handleSendData,this,pBuffer,nBufferSize,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred)); } else { //同步发送 m_sockUdp->send_to(boost::asio::buffer(pBuffer,nBufferSize),m_endpointBroadcast); } } return 0; } //接收数据 void UdpLinkServer::RecvDataProcess(RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2) { //异步接收数据 m_sockUdp->async_receive_from(boost::asio::buffer(m_recvBuf),m_endpointRemote,boost::bind(&UdpLinkServer::handleRecvData,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred,pfunc,dwUserData1,dwUserData2)); } //接收数据处理(手动),就进入本函数响应处理 void UdpLinkServer::handleRecvDataByManual(RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2) { if(IsStop()) return; //下一次接收 RecvDataProcess(pfunc,dwUserData1,dwUserData2); } //当收到客户端数据时,就进入本函数响应处理 void UdpLinkServer::handleRecvData(const boost::system::error_code& error,std::size_t bytes_transferred,RecvDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2) { if(IsStop()) return; //如果没有出错 if(!error || error==boost::asio::error::message_size) { if(bytes_transferred > UDP_DATA_PACKAGE_MAX_LENGTH) { //超过最大数据长度 return; } /* //打印接收的内容 char szTmp[UDP_DATA_PACKAGE_MAX_LENGTH] = {0}; memcpy(szTmp,m_recvBuf.data(),bytes_transferred); printf("%s\n",szTmp); //boost::shared_ptr<std::string> strMessage(new std::string("aaaaaa")); //SendData((char *)strMessage.data(),strMessage.size()); std::string strMessage = "aaaaaaaaaa"; SendDataEx(m_endpointRemote,(char *)strMessage.data(),strMessage.size(),SendDataCallbackOuter,(int)this,0); */ //回调数据 if(pfunc != NULL) { pfunc(error,m_recvBuf.data(),bytes_transferred,(char *)m_endpointRemote.address().to_string().c_str(),m_endpointRemote.port(),dwUserData1,dwUserData2); } //下一次接收 RecvDataProcess(pfunc,dwUserData1,dwUserData2); } else { //出错 if(pfunc != NULL) { pfunc(error,NULL,bytes_transferred,NULL,0,dwUserData1,dwUserData2); } } } //当发送数据给客户端成功之后响应。 void UdpLinkServer::handleSendData(char *pBuffer,int nBufferSize,const boost::system::error_code& error,std::size_t bytes_transferred) { int n = 0; } void UdpLinkServer::handleSendDataInner(SendDataCallback pfunc,DWORD dwUserData1,DWORD dwUserData2,const boost::system::error_code& error,std::size_t bytes_transferred) { if(error != NULL) { //打印错误信息 printf("%s", boost::system::system_error(error).what()); } if(pfunc != NULL) { pfunc(error,bytes_transferred,dwUserData1,dwUserData2); } int n = 0; } /* void UdpLinkServer::handleSendData(boost::shared_ptr<std::string> strMessage,const boost::system::error_code& error,std::size_t bytes_transferred) { int n = 0; } */
// UdpbroastSender.cpp : 定义控制台应用程序的入口点。 //Udpbroast Sender #include "stdafx.h" #include "UdpLinkServer.h" #include <boost/thread/thread.hpp> //设备信息 typedef struct tagDeviceInfo{ unsigned short usFunction; //功能码 unsigned short usVersionFlag; //版本标记 unsigned int uiCompanyId; //企业id char szDeviceSerialNo[24]; //设备序列号 unsigned short usServicePort; //数据服务端口 char szExtend[38]; //扩展 }DeviceInfo; //工作线程参数 typedef struct tagWorkThreadParameter{ boost::asio::io_service * pIoService; UdpLinkServer * pUdpService; }WorkThreadParameter; //工作线程函数处理函数 bool g_WorkThreadExit = false; int g_nBroastDataSendInteral = 5000; //广播发送间隔,单位:毫秒 DeviceInfo g_diDeviceInfo = {0}; //设备信息 unsigned int __stdcall WorkThreadFunByDeviceServiceProcess(PVOID pParam) { int nn = 0; int nDataSize = sizeof(DeviceInfo); WorkThreadParameter *pAllParameter = (WorkThreadParameter *)pParam; while(true) { if(g_WorkThreadExit) { break; } //发送数据 pAllParameter->pUdpService->SendData((char *)&g_diDeviceInfo,nDataSize,true); pAllParameter->pIoService->poll(); for(nn=g_nBroastDataSendInteral;nn>0; nn-=200) { if(g_WorkThreadExit) { break; } Sleep(200); } } return 0; } int main(int argc, char* argv[]) { boost::asio::io_service ioService; UdpLinkServer usUdpService(9090,true);//true,为广播模式;false,非广播模式 usUdpService.Start(ioService); g_diDeviceInfo.usFunction = 1; g_diDeviceInfo.usVersionFlag = 0x0001; strcpy(g_diDeviceInfo.szDeviceSerialNo,"ABCDEFG111111111"); g_diDeviceInfo.usServicePort = 9001; WorkThreadParameter wtpWorkThreadParameter; wtpWorkThreadParameter.pIoService = &ioService; wtpWorkThreadParameter.pUdpService = &usUdpService; //开启线程 boost::thread thrd(WorkThreadFunByDeviceServiceProcess,&wtpWorkThreadParameter); //线程poll等待 thrd.join(); g_WorkThreadExit = true; usUdpService.Stop(); ioService.stop(); return 0; }
// UdpbroastRevicer.cpp : 定义控制台应用程序的入口点。 //Udpbroast Revicer #include "stdafx.h" #include "UdpLinkServer.h" #include <boost/thread/thread.hpp> //设备信息 typedef struct tagDeviceInfo{ unsigned short usFunction; //功能码 unsigned short usVersionFlag; //版本标记 unsigned int uiCompanyId; //企业id char szDeviceSerialNo[24]; //设备序列号 unsigned short usServicePort; //数据服务端口 char szExtend[38]; //扩展 }DeviceInfo; //工作线程函数处理函数 bool g_WorkThreadExit = false; int g_nBroastDataSendInteral = 5000; //广播发送间隔,单位:毫秒 DeviceInfo g_diDeviceInfo = {0}; //设备信息 unsigned int __stdcall WorkThreadFunByDeviceServiceProcess(PVOID pParam) { int nn = 0; boost::asio::io_service * pIoService = (boost::asio::io_service *)pParam; while(true) { if(g_WorkThreadExit) { break; } pIoService->poll(); for(nn=g_nBroastDataSendInteral;nn>0; nn-=200) { if(g_WorkThreadExit) { break; } Sleep(200); } } return 0; } static void WINAPI BroastDeviceInfoRecvDataCallback(const boost::system::error_code& error,char *pData,int nDataLength,char *pPeerIp,unsigned short usPeerPort,DWORD dwUserData1,DWORD dwUserData2) { SYSTEMTIME sm; GetLocalTime(&sm); char szInfo[256] = {0}; DeviceInfo *pDeviceInfo = (DeviceInfo *)pData; sprintf(szInfo,"%s %s:%d time:%04d-%02d-%0d %02d:%02d:%02d\n",pDeviceInfo->szDeviceSerialNo,pPeerIp,usPeerPort,sm.wYear,sm.wMonth,sm.wDay,sm.wHour,sm.wMinute,sm.wSecond); printf(szInfo); } int main(int argc, char* argv[]) { boost::asio::io_service ioService; UdpLinkServer usUdpService(9090,false); usUdpService.SetRecvDataCallback(true,BroastDeviceInfoRecvDataCallback,0,0); usUdpService.Start(ioService); //开启线程 boost::thread thrd(WorkThreadFunByDeviceServiceProcess,&ioService); //线程poll等待 thrd.join(); g_WorkThreadExit = true; usUdpService.Stop(); ioService.stop(); return 0; }
boost库之udp广播实例的更多相关文章
- Boost库实现线程池学习及线程实现的异步调用
A.Boost线程池实现 参考自: Boost库实现线程池实例 原理:使用boost的thread_group存储多个线程,使用bind方法将要处理的函数转换成线程可调用的函数进行执行:使用队列存储待 ...
- boost库区间range基本原理及使用实例
由 www.169it.com 搜集整理 区间的概念类似于STL中的容器概念.一个区间提供了可以访问半开放区间[first,one_past_last)中元素的迭代器,还提供了区间中的元素数量的信息. ...
- boost库在工作(37)网络UDP服务端之七
前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...
- boost库在工作(39)网络UDP异步服务端之九
前面创建的UDP服务器和客户端,都是同步的方式,也就是说当接收数据时,不能参与别的事情执行的.如果在一个只有界面线程的程序里,又不想创建多线程,导致复杂程度的增加,在这种情况之下,我们还有一个方案可以 ...
- netty的Udp单播、组播、广播实例+Java的Udp单播、组播、广播实例
网络上缺乏netty的udp的单播.组播案例,经过一番学习总结之后终于把这两个案例调通,下面把这两个案例的代码放在这里分享一下. 首先推荐博文: http://colobu.com/2014/10/2 ...
- C++ | boost库 类的序列化
是的,这是今年的情人节,一篇还在研究怎么用的文章,文结的时候应该就用成功了. 恩,要有信心 神奇的分割线 不知何时装过boost库的header-only库, 所以ratslam中的boost是可以编 ...
- Python和C|C++的混编(一):Python调用C、C++---Boost库
不使用boost.python库来直接构建dll的话比较繁琐,下面实例是借助boost库实现python对C.C++的调用 1 首先确定已经安装python和boost库,本例测试环境是python2 ...
- (七)boost库之单例类
(七)boost库之单例类 一.boost.serialzation的单件实现 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一 ...
- boost库之shared_ptr
shared_ptr 编辑 目录 1简介 2作用 3历史 4概要 5用法 ▪ 删除共享对象 ▪ 标准容器 1简介编辑 shared_ptr是一种智能指针(smart pointer). 2作用编辑 s ...
随机推荐
- 非root权限 安装更新gcc
本文主要参考网络上文章,并根据自己安装出现的问题进行补充. 参考文章: 1.gcc和boost的升级步骤(非root权限):https://blog.csdn.net/u010246947/artic ...
- 20145331 《Java程序设计》第10周学习总结
20145331 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置 ...
- Elasticsearch之几个重要的分词器
前提 什么是倒排索引? Elasticsearch之分词器的作用 Elasticsearch之分词器的工作流程 Elasticsearch之停用词 Elasticsearch之中文分词器 Elasti ...
- 梅森素数应用 nefu 120
梅森素数 定义: if m是一个正整数 and 2^m-1是一个素数 then m是素数 if m是一个正整数 and m是一个素数 then M(m)=2^m-1被称为第m个梅森数 if p是一个素 ...
- 2017ACM/ICPC广西邀请赛-重现赛 1001 A Math Problem
2017-08-31 16:48:00 writer:pprp 这个题比较容易,我用的是快速幂 写了一次就过了 题目如下: A Math Problem Time Limit: 2000/1000 M ...
- 08_MySQL DQL_SQL99标准中的多表查询(内连接)
# sql99语法/*语法: select 查询列表 from 表1 别名 [连接类型] join 表2 别名 on 连接条件 [where 筛选条件] [group by 分组] [having 分 ...
- 05_zookeeper_原生API使用1(更新)
1. java方式操作远端zookeeper集群概述 步骤:下载zookeeper压缩包并解压, 创建java工程,导入zookeeper相关jar包 (1)下载zookeeper压缩包 http:/ ...
- stdclass
$item = new stdClass(); $item->goods_id = $item_goods->getID(); $item->goods_name ...
- TileMode(平铺模式) 枚举的成员:
TileMode(平铺模式) 枚举的成员: 成员名称 说明 FlipX 与 Tile 相同,只不过图块的交替列被水平翻转. 基本图块本身不翻转. FlipXY FlipX 和 FlipY ...
- Apache的三种工作模式及相关配置
Apache的三种工作模式 作为老牌服务器,Apache仍在不断地发展,就目前来说,它一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块).它们分别是 prefor ...