UDP通讯之字节流与protobuf转换(C++版)

UDP通讯之字节流与protobuf转换(C++版)

    • 说明
    • 工程内容
      • VS2017工程介绍
      • VS2017工程基本设置
      • 数据结构体
      • UDP服务端server与客户端client类的封装
      • 初始化IP与Port的配置文件(ini格式)的封装
      • 大小端转换类的封装
      • 主函数的介绍与使用
      • 另一台电脑调用

说明

  • 只做了车辆信息与控制信息两部分,简易流程图如下
  • 工程在VS2017下用C++编写完成,已经做过初步测试,可以通讯使用
  • 所有通讯内容是proto2版本,亲测装的proto3版本可以兼容使用
  • 有一个大小端转换问题,阳哥控制接收端与我这边UDP发送大小端相反,做了一下转换
    UDP通讯之字节流与protobuf转换(C++版)_第1张图片

工程内容

  • VS2017基本设置与工程介绍
  • UDP服务端server与客户端client类的封装
  • 初始化IP与Port的配置文件(ini格式)的封装
  • 大小端转换类的封装
  • 主函数的介绍与使用

VS2017工程介绍

  • 解决方案名称TestOfProtobuf下包含两个项目工程,第一个SimulatorDataExchange为最终完成的项目,第二个为第一版测试,可以忽略。
  • SimulatorDataExchange工程项目下头文件构成。
    UDP通讯之字节流与protobuf转换(C++版)_第2张图片
  • imulatorDataExchange工程项目下源文件构成。
    UDP通讯之字节流与protobuf转换(C++版)_第3张图片
  • 资源文件要将所有用到的proto文件加载进来。
    UDP通讯之字节流与protobuf转换(C++版)_第4张图片

VS2017工程基本设置

  • 注意工程是Debug还是Release,64位还是32位,这个要跟protobuf编译时要一致,我使用的是Debug64位。
  • 右键点击项目,打开属性
    UDP通讯之字节流与protobuf转换(C++版)_第5张图片
  • C/C++中附加包含目录:包含你的protobuf版本的google头文件。
  • 下面的SDL检查设为否(/sdl-)
    UDP通讯之字节流与protobuf转换(C++版)_第6张图片
  • C/C++中代码生成运行库为多线程调试(/MTd)
    在这里插入图片描述
  • 链接器下附加库目录:将你protobuf编译出来的三个lib文件目录指定
    UDP通讯之字节流与protobuf转换(C++版)_第7张图片
  • 链接器下输入->附加依赖项:将三个lib名字加进去。
    UDP通讯之字节流与protobuf转换(C++版)_第8张图片

数据结构体

  • Message.h文件
#pragma once
struct CarMsg//对应车辆信息结构体
{
	long long utime;
	int nauto;
	float steerPos;
	int steerSpe;
	int light;
	float speLeft;   // KM/H
	float speRight;
	float vot;
	int shift;   //PRND
	float disLeft;
	float disRight;
	float speo;
	float yawRate; //y轴角速度 弧度/秒
	float accelerationLon;
	float accelerationLat;
};
struct GPSMsg//对应GPS信息结构体
{
	long long utime;
	double longitude;
	double latitude;
	float altitude;
	float yaw;
	float roll;
	float pitch;
	float yawRate;
	float velocityNorth;
	float velocityEast;
	float velocityDown;
	float accelerationLongitudinal;
	float accelerationLateral;
	float acceleration;
	float velocity;
	float locationStatus;
	float confidenceLevel;
	float yawEstimate;
	double longitudeEstimate;
	double latitudeEstimate;
	short satelliteNumber;
};
struct ControlMsg//对应控制信息结构体
{
	long long utime;
	double throttle;
	double brake;
	double steeringRate; //方向盘转动速率绝对值 0~100
	double steeringTarget;   //+-520,左正右负
	double speed;
	double acceleration;
	bool engineOnOff;
	bool leftTurn;
	bool rightTurn;
	bool horn;
	bool parkingBrake;
	bool resetModel;
	short drivingMode;
	short gearLocation;
};
struct TrafficLightMsg//交通灯信息结构体
{
	long utime;
	unsigned char light;  //0,1,2,3三种状态,分别表示未知,红灯,黄灯,绿灯
	float distance;     //距停止线的距离
	float time;	        //剩余时间
};
struct ControlMsgChangeBS//控制信息大小端转换暂存数据结构体
{
	long long utime;
	double throttle;
	double brake;
	double steeringRate; //方向盘转动速率绝对值 0~100
	double steeringTarget;   //+-520,左正右负
	double speed;
	double acceleration;
	bool engineOnOff;
	bool leftTurn;
	bool rightTurn;
	bool horn;
	bool parkingBrake;
	bool resetModel;
	short drivingMode;
	short gearLocation;
};

UDP服务端server与客户端client类的封装

  • UDPClient.cpp
#include "UDPClient.h"//引入头文件
#include <iostream>
using namespace std;
UDPClient::UDPClient(const char name[14])//构造函数与类名相同,初始化类时自动执行
{
	WSAStartup(MAKEWORD(2, 2), &ws);//初始化
	clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//创建socket
	std::cout << "**********************************************************" << std::endl;
	cout << name << " Client Socket initialized Successful" << endl;
	std::cout << "**********************************************************" << std::endl;
	std::cout << std::endl;
}
UDPClient::~UDPClient()//析构函数,在对象销毁时自动执行,用于清理工作
{
	closesocket(clientSocket);
	WSACleanup();
	cout << "Client Socket released" << endl;
}
void UDPClient::setSockAddr(char *destAddr,int destPort)//设置IP和Port
{
	clientSockAddr.sin_family = AF_INET;
	clientSockAddr.sin_port = htons(destPort);
	clientSockAddr.sin_addr.s_addr = inet_addr(destAddr);
}
void UDPClient::sendData(char *buf,int len)//发送函数
{
	sendto(clientSocket, buf, len, 0, (SOCKADDR*)&clientSockAddr, sizeof(clientSockAddr));
}
  • UDPClient.h
#pragma once
#include <WINSOCK2.H>
#pragma comment(lib, "WS2_32.lib")
using namespace std;
class UDPClient
{
private:
	WSADATA ws;
	SOCKET clientSocket;
	SOCKADDR_IN clientSockAddr;
public:
	UDPClient(const char name[14]);//函数声明,与UDPClient.cpp对应
	void setSockAddr(char *destAddr,int destPort);
	void sendData(char *buf,int len);
	~UDPClient();
};
  • UDPServer.cpp
#include"UDPServer.h"
#include<iostream>
using namespace std;
UDPServer::UDPServer()//构造函数,与类名相同,初始化类时自动执行
{
	WSAStartup(MAKEWORD(2, 2), &wsaData);//初始化
	serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//创建socket
}
void UDPServer::listen(int port,const char name[14])//绑定端口
{
	serverSockAddr.sin_family = AF_INET;
	serverSockAddr.sin_port = htons(port);
	serverSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(serverSocket, (SOCKADDR*)&serverSockAddr, sizeof(serverSockAddr)) == 0)
	{
		std::cout << "**********************************************************" << std::endl;
		cout << name << " Server Socket initialized Successful" << endl;
		std::cout << "**********************************************************" << std::endl;
		std::cout << std::endl;
	}
	else
	{
		std::cout << "**********************************************************" << std::endl;
		cout << name << "Server Socket initialized Failed" << endl;
		std::cout << "**********************************************************" << std::endl;
		std::cout << std::endl;
	}
}
void UDPServer::receive(char *buf,int len)//接收函数
{
	int serverSockAddrSize = sizeof(SOCKADDR);
	recvfrom(serverSocket, buf, len, 0, (SOCKADDR *)&serverSockAddr, &serverSockAddrSize);
}
UDPServer::~UDPServer()//析构函数,在对象销毁时自动执行,用于清理工作
{
	closesocket(serverSocket);
	WSACleanup();
	cout << "Server Socket released" << endl;
}
  • UDPServer.h
#pragma once
#include <WINSOCK2.H>
#pragma comment(lib, "WS2_32.lib")
using namespace std;
class UDPServer 
{
private:
	WSADATA wsaData;
	SOCKET serverSocket;
	sockaddr_in serverSockAddr;
public:
	UDPServer();//函数声明,与UDPServer.cpp对应
	void listen(int port, const char name[14]);
	void receive(char *buf,int len);
	~UDPServer();
};

初始化IP与Port的配置文件(ini格式)的封装

  • 网上当的ini读取配置文件功能,包括inifile.h头文件和infile.cpp源文件加载即可,程序比较长就不做展示了.
  • SimulatorDataExchange.ini
;UDPSend IP or Port//;代表屏蔽这一行,起到提示作用
[UdpCarMsgReceive]//[]代表标志头,用来识别读取哪个标志头下在内容
IP=127.0.0.1//IP=127.0.0.1 IP为变量名
Port=8025
[UdpCarMsgSend]
IP=127.0.0.1
Port=8029
[UdpGpsMsgReceive]
IP=127.0.0.1
Port=8026
[UdpControlMsgReceive]
IP=127.0.0.1
Port=8027
[UdpControlMsgSend]
IP=127.0.0.1
Port=8027
  • 主函数中实现 ini数据读取
void readINI()//初始化函数,只运行一次
{
	std::cout << "**********************************************************" << std::endl;
	std::cout << "          SIMULATOR DATA OF UDP RECEIVE AND SEND               " << std::endl;
	std::cout << "**********************************************************" << std::endl;
	std::cout << std::endl;
	//声明ini初始化接口ini
	CIniFileA ini;
	//加载ini文件,所以ini文件一定要放在当前目录
	ini.Load("SimulatorDataExchange.ini");
	//ReceiveCarMsg ip and port
	std::string carReceiveIP = ini.GetKeyValue("UdpCarMsgReceive", "IP");
	strcpy(ip_ReceiveCarMsg, carReceiveIP.c_str());
	std::string carReceivePort = ini.GetKeyValue("UdpCarMsgReceive", "Port");
	port_ReceiveCarMsg = std::atoi(carReceivePort.c_str());
	//SendCarMsg ip and port
	std::string carSendIP = ini.GetKeyValue("UdpCarMsgSend", "IP");
	strcpy(ip_SendCarMsg, carSendIP.c_str());
	std::string carSendPort = ini.GetKeyValue("UdpCarMsgSend", "Port");
	port_SendCarMsg = std::atoi(carSendPort.c_str());
	//ReceiveGPS ip and port
	std::string gpsIP = ini.GetKeyValue("UdpGpsMsgReceive","IP");
	strcpy(ip_ReceiveGPSMsg, gpsIP.c_str());
	std::string gpsPort = ini.GetKeyValue("UdpGpsMsgReceive", "Port");
	port_ReceiveGPSMsg = std::atoi(gpsPort.c_str());
	//ReceiveControlMsg ip and port
	std::string controlReceiveIP = ini.GetKeyValue("UdpControlMsgReceive", "IP");
	strcpy(ip_ReceiveControlMsg, controlReceiveIP.c_str());
	std::string controlReceivePort = ini.GetKeyValue("UdpControlMsgReceive", "Port");
	port_ReceiveControlMsg = std::atoi(controlReceivePort.c_str());
	//SendControlMsg ip and port
	std::string controlSendIP = ini.GetKeyValue("UdpControlMsgSend", "IP");
	strcpy(ip_SendControlMsg, controlSendIP.c_str());
	std::string controlSendPort = ini.GetKeyValue("UdpControlMsgSend", "Port");
	port_SendControlMsg = std::atoi(controlSendPort.c_str());

	if (!ip_ReceiveCarMsg && !port_ReceiveCarMsg && !ip_SendCarMsg && !port_SendCarMsg)
	{
		std::cout << "**********************************************************" << std::endl;
		std::cout << "         CONFIGURE COMMUNICATION IP AND PORT  FAILED             " << std::endl;
		std::cout << "**********************************************************" << std::endl;
	}
	else
	{
		std::cout << "**********************************************************" << std::endl;
		std::cout << "         CONFIGURE COMMUNICATION IP AND PORT  SUCCESS            " << std::endl;
		std::cout << "**********************************************************" << std::endl;
	}
}

大小端转换类的封装

  • ChangeBS.cpp
#include "stdafx.h"
#include "ChangeBS.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CChangeBS::CChangeBS()
{
}
CChangeBS::~CChangeBS()
{
}
void CChangeBS::OnChange(short InParam, short &OutParam)
{
	union
	{
		char ch[2];
		unsigned short iTemp;
	}u,r;
	u.iTemp = InParam;
	r.ch[0] = u.ch[1];
	r.ch[1] = u.ch[0];
	OutParam = r.iTemp;
}
void CChangeBS::OnChange(int InParam, int &OutParam)
{
	union
	{
		char ch[4];
		int iTemp;
	}u,r;
	u.iTemp = InParam;
	r.ch[0] = u.ch[3];
	r.ch[1] = u.ch[2];
	r.ch[2] = u.ch[1];
	r.ch[3] = u.ch[0];
	OutParam = r.iTemp;
}
void CChangeBS::OnChange(float InParam, float &OutParam)
{
	union
	{
		char ch[4];
		float iTemp;
	}u,r;
	u.iTemp = InParam;
	r.ch[0] = u.ch[3];
	r.ch[1] = u.ch[2];
	r.ch[2] = u.ch[1];
	r.ch[3] = u.ch[0];
	OutParam = r.iTemp;
}
void CChangeBS::OnChange(double InParam, double &OutParam)
{
	union
	{
		char ch[8];
		double iTemp;
	}u,r;
	u.iTemp = InParam;
	r.ch[0] = u.ch[7];
	r.ch[1] = u.ch[6];
	r.ch[2] = u.ch[5];
	r.ch[3] = u.ch[4];
	r.ch[4] = u.ch[3];
	r.ch[5] = u.ch[2];
	r.ch[6] = u.ch[1];
	r.ch[7] = u.ch[0];
	OutParam = r.iTemp;
}
void CChangeBS::OnChange(long long InParam, long long &OutParam)
{
	union
	{
		char ch[8];
		long long iTemp;
	}u, r;
	u.iTemp = InParam;
	r.ch[0] = u.ch[7];
	r.ch[1] = u.ch[6];
	r.ch[2] = u.ch[5];
	r.ch[3] = u.ch[4];
	r.ch[4] = u.ch[3];
	r.ch[5] = u.ch[2];
	r.ch[6] = u.ch[1];
	r.ch[7] = u.ch[0];
	OutParam = r.iTemp;
}
  • ChangeBS.h
#if !defined(AFX_CHANGEBS_H__A852EEC4_2B3E_431B_B522_12BA81B648DA__INCLUDED_)
#define AFX_CHANGEBS_H__A852EEC4_2B3E_431B_B522_12BA81B648DA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CChangeBS  
{
public:
	CChangeBS();
	virtual ~CChangeBS();
public:
	static void OnChange(short  InParam, short  &OutParam);
	static void OnChange(int	 InParam, int	 &OutParam);
	static void OnChange(float  InParam, float  &OutParam);
	static void OnChange(double InParam, double &OutParam);
	static void OnChange(long long InParam, long long &OutParam);
};
#endif // !defined(AFX_CHANGEBS_H__A852EEC4_2B3E_431B_B522_12BA81B648DA__INCLUDED_)

主函数的介绍与使用

  • SimulatorDataExchange.cpp
#include "chassis.pb.h"
#include "drive_state.pb.h"
#include "error_code.pb.h"
#include "geometry.pb.h"
#include "header.pb.h"
#include "vehicle_signal.pb.h"
#include "control_cmd.pb.h"
#include "pad_msg.pb.h"
#include "UDPClient.h"
#include "UDPServer.h"
#include "inifile.h"
#include "Message.h"
#include "ChangeBS.h"
#include <time.h>
#include <string.h>
#include <thread>//引入多线程头文件
#include <iostream>
//创建空字符,用于存储读取在IP
char ip1[12] = { NULL };
char ip2[12] = { NULL };
char ip3[12] = { NULL };
char ip4[12] = { NULL };
char ip5[12] = { NULL };
//ReceiveCarMsg ip and port
char* ip_ReceiveCarMsg = ip1;
int port_ReceiveCarMsg = NULL;
const int buffer_ReceiveCarMsg = 1024;
//SendCarMsg ip and port
char* ip_SendCarMsg = ip2;
int port_SendCarMsg = NULL;
const int buffer_SendCarMsg = 1024;
//SendControlMsg ip and port
char* ip_SendControlMsg = ip3;
int port_SendControlMsg = NULL;
const int buffer_SendControlMsg = 1024;
//ReceiveControlMsg ip and port
char* ip_ReceiveControlMsg = ip4;
int port_ReceiveControlMsg = NULL;
const int buffer_ReceiveControlMsg = 1024;
//ReceiveGPS ip and port
char* ip_ReceiveGPSMsg = ip5;
int port_ReceiveGPSMsg = NULL;
const int buffer_ReceiveGPSMsg = 1024;
CarMsg carmsg;//创建结构体数据别名
ControlMsg controlmsg;//创建结构体数据别名
ControlMsgChangeBS bs;//创建结构体数据别名
readINI()//读取ini配置文件在IP和Port
{
	std::cout << "**********************************************************" << std::endl;
	std::cout << "          SIMULATOR DATA OF UDP RECEIVE AND SEND               " << std::endl;
	std::cout << "**********************************************************" << std::endl;
	std::cout << std::endl;
	CIniFileA ini;
	ini.Load("SimulatorDataExchange.ini");
	//ReceiveCarMsg ip and port
	std::string carReceiveIP = ini.GetKeyValue("UdpCarMsgReceive", "IP");
	strcpy(ip_ReceiveCarMsg, carReceiveIP.c_str());
	std::string carReceivePort = ini.GetKeyValue("UdpCarMsgReceive", "Port");
	port_ReceiveCarMsg = std::atoi(carReceivePort.c_str());
	//SendCarMsg ip and port
	std::string carSendIP = ini.GetKeyValue("UdpCarMsgSend", "IP");
	strcpy(ip_SendCarMsg, carSendIP.c_str());
	std::string carSendPort = ini.GetKeyValue("UdpCarMsgSend", "Port");
	port_SendCarMsg = std::atoi(carSendPort.c_str());
	//ReceiveGPS ip and port
	std::string gpsIP = ini.GetKeyValue("UdpGpsMsgReceive","IP");
	strcpy(ip_ReceiveGPSMsg, gpsIP.c_str());
	std::string gpsPort = ini.GetKeyValue("UdpGpsMsgReceive", "Port");
	port_ReceiveGPSMsg = std::atoi(gpsPort.c_str());
	//ReceiveControlMsg ip and port
	std::string controlReceiveIP = ini.GetKeyValue("UdpControlMsgReceive", "IP");
	strcpy(ip_ReceiveControlMsg, controlReceiveIP.c_str());
	std::string controlReceivePort = ini.GetKeyValue("UdpControlMsgReceive", "Port");
	port_ReceiveControlMsg = std::atoi(controlReceivePort.c_str());
	//SendControlMsg ip and port
	std::string controlSendIP = ini.GetKeyValue("UdpControlMsgSend", "IP");
	strcpy(ip_SendControlMsg, controlSendIP.c_str());
	std::string controlSendPort = ini.GetKeyValue("UdpControlMsgSend", "Port");
	port_SendControlMsg = std::atoi(controlSendPort.c_str());
	if (!ip_ReceiveCarMsg && !port_ReceiveCarMsg && !ip_SendCarMsg && !port_SendCarMsg)
	{
		std::cout << "**********************************************************" << std::endl;
		std::cout << "         CONFIGURE COMMUNICATION IP AND PORT  FAILED             " << std::endl;
		std::cout << "**********************************************************" << std::endl;
	}
	else
	{
		std::cout << "**********************************************************" << std::endl;
		std::cout << "         CONFIGURE COMMUNICATION IP AND PORT  SUCCESS            " << std::endl;
		std::cout << "**********************************************************" << std::endl;
	}
}
//车辆信息接收,字节流解析
void carMsgReceive(int port,const char name[14])
{
	char receivebuff[buffer_ReceiveCarMsg] = { 0 };
	UDPServer* server = new UDPServer;
	server->listen(port,name);
	while (true)
	{
		server->receive(receivebuff, sizeof(receivebuff));
		memcpy(&carmsg.utime,&receivebuff[0],8);
		memcpy(&carmsg.nauto,&receivebuff[8],4);
		memcpy(&carmsg.steerPos, &receivebuff[12],4);
		memcpy(&carmsg.steerSpe, &receivebuff[16], 4);
		memcpy(&carmsg.light, &receivebuff[20], 4);
		memcpy(&carmsg.speLeft, &receivebuff[24], 4);
		memcpy(&carmsg.speRight, &receivebuff[28], 4);
		memcpy(&carmsg.vot, &receivebuff[32], 4);
		memcpy(&carmsg.shift, &receivebuff[36], 4);
		memcpy(&carmsg.disLeft, &receivebuff[40], 4);
		memcpy(&carmsg.disRight, &receivebuff[44], 4);
		memcpy(&carmsg.speo, &receivebuff[48], 4);
		memcpy(&carmsg.yawRate, &receivebuff[52], 4);
		memcpy(&carmsg.accelerationLon, &receivebuff[56], 4);
		memcpy(&carmsg.accelerationLat, &receivebuff[60], 4);
		std::cout << "CarMsg:" << carmsg.utime <<std::endl;
	}
	delete server;
	std::cout << "ReceiveCarMsg Server Destroyed" << std::endl;
}
//控制信息接收,protobuf解析
void controlMsgReceive(int port, const char name[14])
{
	char receivebuff[buffer_ReceiveControlMsg] = { 0 };
	UDPServer* server = new UDPServer;
	server->listen(port, name);
	ab::control::ControlCommand *control = new ab::control::ControlCommand();
	while (true)
	{
		server->receive(receivebuff, sizeof(receivebuff));
		control->ParseFromArray(receivebuff, sizeof(receivebuff));
		controlmsg.throttle = control->throttle();
		controlmsg.brake = control->brake();
		controlmsg.steeringRate = control->steering_rate();
		controlmsg.steeringTarget = control->steering_target() * 520;
		controlmsg.speed = control->speed();
		controlmsg.acceleration = control->acceleration();
		controlmsg.engineOnOff = control->engine_on_off();
		controlmsg.parkingBrake = control->parking_brake();
		controlmsg.horn = control->horn();
		controlmsg.resetModel = control->reset_model();
		int turn = control->turnsignal();
		if (turn == 0)
		{
			controlmsg.leftTurn = 0;
			controlmsg.rightTurn = 0;
		}
		else if (turn == 1)
		{
			controlmsg.leftTurn = 1;
			controlmsg.rightTurn = 0;
		}
		else
		{
			controlmsg.leftTurn = 0;
			controlmsg.rightTurn = 1;
		}
		controlmsg.drivingMode = control->driving_mode();
		controlmsg.gearLocation = control->gear_location();
	}
	delete server;
	std::cout << "ReceiveControlMsg Server Destroyed" << std::endl;
}
//车辆信息发送,protobuf序列化
void carMsgSend(const int port,char *address, float time, const char name[14])
{
	char sendbuff[buffer_SendCarMsg] = { 0 };
	clock_t start, end;
	start = clock();
	UDPClient* client = new UDPClient(name);
	client->setSockAddr(address, port);
	ab::vehicle::Chassis *carmsg_send = new ab::vehicle::Chassis();
	ab::common::VehicleSignal *vehiclesignal = new ab::common::VehicleSignal();
	while (true)
	{
		//时间戳
		carmsg_send->set_steering_timestamp(carmsg.utime);
		//驾驶模式
		carmsg_send->set_driving_mode(ab::vehicle::Chassis_DrivingMode(carmsg.nauto));
		//挡位
		carmsg_send->set_gear_location(ab::vehicle::Chassis_GearPosition(carmsg.shift));
		//转角百分比 = 转角/520
		carmsg_send->set_steering_percentage(carmsg.steerPos/520);
		//转向灯
		vehiclesignal->set_turn_signal(ab::common::VehicleSignal_TurnSignal(carmsg.light));
		//前轮速度
		carmsg_send->set_speed_mps((carmsg.speLeft+carmsg.speRight)/7.2);
		carmsg_send->SerializeToArray(sendbuff, sizeof(sendbuff));
		end = clock();
		if (end - start > time)
		{
			client->sendData(sendbuff, sizeof(sendbuff));
			start = end;
		}
		Sleep(1);
	}
	delete client;
}
//控制信息发送,字节流发送
void controlMsgSend(const int port, char *address, float time, const char name[14])
{
	char sendbuff[buffer_SendControlMsg] = { 0 };
	clock_t start, end;
	start = clock();
	UDPClient* client = new UDPClient(name);
	client->setSockAddr(address, port);
	while (true)
	{	
		//大小端转换
		CChangeBS::OnChange(controlmsg.utime, bs.utime);
		CChangeBS::OnChange(controlmsg.throttle, bs.throttle);
		CChangeBS::OnChange(controlmsg.brake, bs.brake);
		CChangeBS::OnChange(controlmsg.steeringRate, bs.steeringRate);
		CChangeBS::OnChange(controlmsg.steeringTarget, bs.steeringTarget);
		CChangeBS::OnChange(controlmsg.speed, bs.speed);
		CChangeBS::OnChange(controlmsg.acceleration, bs.acceleration);
		bs.engineOnOff = controlmsg.engineOnOff;
		bs.leftTurn = controlmsg.leftTurn;
		bs.rightTurn = controlmsg.rightTurn;
		bs.horn = controlmsg.horn;
		bs.parkingBrake = controlmsg.parkingBrake;
		bs.resetModel = controlmsg.resetModel;
		CChangeBS::OnChange(controlmsg.drivingMode, bs.drivingMode);
		CChangeBS::OnChange(controlmsg.gearLocation, bs.gearLocation);
		char* pack = (char *)&bs;
		end = clock();
		if (end - start > time)
		{
			client->sendData(pack, sizeof(sendbuff));
			start = end;
		}
		Sleep(1);
	}
	delete client;
}
int main(int argc, char *argv[])
{
	//初始化配置
	readINI();
	//子线程UDP发送、接收
	std::thread udpReceiveCarMsg(carMsgReceive, port_ReceiveCarMsg, "ReceiveCarMsg");
	udpReceiveCarMsg.detach();
	std::thread udpSendCarMsg(carMsgSend, port_SendCarMsg, ip_SendCarMsg,99, "SendCarMsg");
	udpSendCarMsg.detach();
	std::thread udpReceiveControlMsg(controlMsgReceive, port_ReceiveControlMsg, "ReceiveControlMsg");
	udpReceiveControlMsg.detach();
	std::thread udpSendControlMsg(controlMsgSend, port_SendControlMsg, ip_SendControlMsg, 99, "SendControlMsg");
	udpSendControlMsg.detach();
	//主线程一定要有,否则子线程无法运行
	while (true)
	{
		Sleep(100);
	}
}

另一台电脑调用

  • VS2017编译后会生成exe可执行文件,注意将SimulatorDataExchange.ini配置文件放在exe文件夹下面,同一目录
  • 其他的ilk文件和pdb文件也要放在一起,这是打包的头文件和资源文件等压缩的.
    UDP通讯之字节流与protobuf转换(C++版)_第9张图片
  • 运行效果
    UDP通讯之字节流与protobuf转换(C++版)_第10张图片

你可能感兴趣的:(原创)