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 ...
随机推荐
- https nginx配置
cd /saas/conf/nginx/ mkdir key cd key 创建key: openssl req -nodes -newkey rsa:2048 -keyout server.key ...
- golang test 单元测试
golang自家的单元测试做的很好了,自需要"文件名_test.go" 就可以在里面写单元测试,而且go test命令也很强大,可以只运行单个测试函数,在goland 可以点击单元 ...
- RocEDU.阅读.写作《苏菲的世界》书摘(二)
"迷信",多么奇怪的一个名词.如果你信基督教或伊斯兰教,这就叫"信仰",但如果你相信占星术或十三号星期五不吉利,就是迷信.谁有权利说别人相信的东西就是" ...
- spring定时器(注解的形式)
最近有个需求,要在凌晨的时候,根据某几张表生成一张定时任务表里的数据,数据的状态为0(未整改),然后在当天晚上,再把这些数据的状态没改变的,改变状态为1(待整改),然后要用到定时器,百度了一下用注解形 ...
- Linux服务器上ftp的搭建和使用
知识点: 1. FTP的简介.工作原理 2.在Linux上搭建FTP服务器 参考: 阿里云文档:https://help.aliyun.com/knowledge_detail/60152.html ...
- 数据结构实习 - problem K 用前序中序建立二叉树并以层序遍历和后序遍历输出
用前序中序建立二叉树并以层序遍历和后序遍历输出 writer:pprp 实现过程主要是通过递归,进行分解得到结果 代码如下: #include <iostream> #include &l ...
- 转载:WEB前端的优化
一.HTML优化 避免使用Iframe Iframe也叫内联frame,可以把一个HTML文档嵌入到另一个文档中.使用iframe的好处是被嵌入的文档可以完全独立于其父文档,凭借此特点我们通常可以使浏 ...
- PIL.Image与Base64 String的互相转换
https://www.jianshu.com/p/2ff8e6f98257 PIL.Image与Base64 String的互相转换 mona_alwyn 2018.01.18 19:02* 字数 ...
- Java编码方式再学
一直以来对编码方式对了解不是很深入.建议读下这几篇博文 学点编码知识又不会死:Unicode的流言终结者和编码大揭秘 编码研究笔记 这几篇博文上回答了内心存在的一些问题,这些问题可能也是大家经常遇到的 ...
- 24.Java中atomic包中的原子操作类总结
1. 原子操作类介绍 在并发编程中很容易出现并发安全的问题,有一个很简单的例子就是多线程更新变量i=1,比如多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchr ...