//前提
boost::shared_ptr<boost::thread> _Thread;
boost::asio::io_service _IOS;
boost::shared_ptr<udp::socket> _Socket;
TSString _MulticastAddress;
//异步调用中run函数说明;
//IOS中的run成员函数可以等待异步操作完成,当异步操作完成时IOS从操作系统获取执行结果,调用完成处理函数;
//在异步调用中run函数是必须的,调用run函数,它启动前摄器的事件处理循环,阻塞等待所有的操作完成并分派事件,
//如果不调用run那么虽然操作被异步执行了,但没有一个等待它完成的机制,回调函数将得不到执行的机会
//IOS的run函数在新建的线程中运行,由于IOS的数据传输工作都是在run中执行,故使用IOS进行UDP/TCP传输都在另起新线程中执行.
_Thread.rest( nwe boost::thread(boost::bind(&boost::asio::io_service::run, &_IOS)) );
boost::asion::ip::udp::endpoint listen_endpoint( udp::v4(), 1010 );
_Socket,reset( new udp::socket(_IOS) );
//修改接收缓冲区大小
_Socket->set_option( boost::asio::socket_base::receive_buffer_size(1024*1024*50) );
_Socket->open( lister_endpoint );
_Socket->set_option( boost::asio::ip::udp::socket::reuse_address(true) );
_Socket->bind( listen_endpoint );
_Socket->set_option( boost::asio::ip::multicast::join_group(boost::asio::ip::address::from_string(TSString2Ascii(_MulticastAddress))) );
①、Struct.h -- 存放传输数据的结构体
//由于不同操作系统之间的字节对齐方式不同,故网络传输数据时,要设置字节对齐方式
//设置变量以n字节对齐方式,指定结构体、联合以及类成员
#pragma pack(push) //保持对齐状态
#pragma pack(1) //设定为1字节对齐
#ifndef _MESSAGE_HEADER
#define _MESSAGE_HEADER
typedef struct _MESSAGE_HEADER
{
unsigned short int uhMessageCode; //消息类型
unsigned short int uhMessageLength; //消息长度
unsigned long int ulTimeTag; //时间
unsigned short int uhSerialNumber; //消息序号;
unsigned char ucSpare[22] //空余位
}SOCKET_MESSAGE_HEADER;
#endif
namespace DateStruct
{
struct DS_STATE
{
char cID[32]; //ID
char cState; //状态
}
}
#pragma pack(pop) //恢复对齐状态
②、使用socket发送数据
{
//消息头;
SOCKET_MESSAGE_HEADER header;
memset( &header, 0, sizeof(header) );
header.uhMessageCode = 2;
//消息体;
DateStruct::DS_STATE sendMsg;
memset( &sendMsg, 0, sizeof(DateStruct::DS_STATE) );
std::string tempID = "LHC010";
memcpy( sendMsg.cID, tempID, sizeof(std::string) );
char tempState("1");
sendMsg.cState = tempState;
//消息体长度;
int bodyLength = sizeof( DateStruct::DS_STATE );
//创建并初始化buffer用于存储 "消息头+消息体";
char * buff = new char[sizeof(header) + bodyLength];
memset( buff, 0, sizeof(header)+ bodyLegth );
//将消息头拷贝到buffer中;
memcpy( buff, &header, sizeof(header) );
//将消息体拷贝到buffer中;
memcpy( buff+sizeof(header), &sendMsg, sizeof(sendMsg) );
//将char*类型转换成char类型,因为boost-udp发送数据时,接收char类型,而非char*类型;
char sendBuff[2000] = {0};
int bLen = sizeof(SOCKET_MESSAGE_HEADER) + sizeof(DateStruct::DS_STATE);
memcpy( sendBuff, buff, bLen );
//使用socket发送数据;
boost::shared_ptr<boost::asio::ip::udp::socket> _ScoketPtr;
boost::asio::ip::udp::endpoint _SendEndPoint;
_SocketPtr.reset( new boost::asio::ip::udp::socket(_IOS) );
_SocketPtr->send_to( boost::asio::buffer(sendBuff), _SendEndPoint, 0 );
}
③ 接收数据-创建UDP
void CreatUDP()
{
_SocketPtr.reset( new boost::asio::ip::udp::socket(_IOS) );
try
{
boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::udp::v4(), _SendPort);
_SocketPtr->open( endpoint.protocol() );
_SocketPtr->bind( endpoint );
_Thread.rest( new boost::thread(&ServerProcRecv, this) );
}
catch( boost::system::system_error e )
{
const char * errMsg = e.what();
}
}
④socket循环接收数据
void ServerProcRecv()
{
size_t len;
boost::system::error_code ec;
//对方(即 发送数据端) 的端口与IP
boost::asio::ip::udp::endpoint revEndpoint;
while(true)
{
char tempBuffer[2000] = {0};
len = _SocketPtr->receive_from( boost::asio::buffer(tempBuffer), revEndpoint, 0, ec );
//发送端IP与端口号;
str::string revIP = revEndpoint.address().to_string();
unsigned short revPort = revEndpoint.port();
if( !ec )
{
if( len > 0 )
{
SOCKET_MESSAGE_HEADER mesHeader;
memcpy( &mesHeader, tempBuffer, sizeof(SOCKET_MESSAGE_HEADER) );
switch( mesHeader.uhMessageCode )
{
case 2:
{
DateStruct::DS_STATE msg;
memcpy( &msg, tempBuffer+sizeof(SOCKET_MESSAGE_HEADER), sizeof(DateStruct::DS_STATE) );
//得到发送过来的消息体msg;
//--TODO:
//--TODO:
break;
}
}
}
}
}
}
本文详细讲解如何在UDP网络通信中传输结构体数据,包括在Struct.h文件中定义结构体,使用socket进行数据发送,创建UDP进行接收,并实现循环接收数据的完整流程。
282

被折叠的 条评论
为什么被折叠?



