BOOST UDP 网络通信(2) --如何传输结构体

本文详细讲解如何在UDP网络通信中传输结构体数据,包括在Struct.h文件中定义结构体,使用socket进行数据发送,创建UDP进行接收,并实现循环接收数据的完整流程。

//前提

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;
					}
				}
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值