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

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

说明

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

工程内容

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

VS2017工程介绍

  • 解决方案名称TestOfProtobuf下包含两个项目工程,第一个SimulatorDataExchange为最终完成的项目,第二个为第一版测试,可以忽略。

  • SimulatorDataExchange工程项目下头文件构成。
  • imulatorDataExchange工程项目下源文件构成。
  • 资源文件要将所有用到的proto文件加载进来。

VS2017工程基本设置

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

数据结构体

  • Message.h文件
#pragma once
struct CarMsg//对应车辆信息结构体
{long long utime;int nauto;float steerPos;int steerSpe;int light;float speLeft;   // KM/Hfloat speRight;float vot;int shift;   //PRNDfloat 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~100double 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~100double 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);//创建socketstd::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初始化接口iniCIniFileA ini;//加载ini文件,所以ini文件一定要放在当前目录ini.Load("SimulatorDataExchange.ini");//ReceiveCarMsg ip and portstd::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 portstd::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 portstd::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 portstd::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 portstd::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 portstd::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 portstd::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 portstd::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 portstd::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 portstd::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));//转角百分比 = 转角/520carmsg_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++版)相关推荐

  1. 关于c语言的udp通讯详细讲解

    目录 1. UDP简介 2. UDP通信流程 3.UDP的函数接口说明 4.UDP通讯测试代码 1. UDP简介 UDP全称 User Datagram Protocol,即:用户数据报协议.是面向无 ...

  2. LWIP裸机环境下实现TCP与UDP通讯(转)

    源: LWIP裸机环境下实现TCP与UDP通讯

  3. 基于Delphi API写的UDP通讯类

    转载地址:http://www.codefans.net/articles/159.shtml 基于Delphi API写的UDP通讯类,可以广播和单播,类作者:王彦鹏.这个类是作者2007年的时候写 ...

  4. LWIP裸机环境下实现TCP与UDP通讯

    前面移植了LWIP,并且简单的实用了DHCP的功能,今天来使用一下实际的数据通讯的功能 首先是实现TCP客户端,我先上代码 #ifndef __TCP_CLIENT_H_ #define __TCP_ ...

  5. linux系统udp通信程序,Linux UDP socket编程(UDP通讯模型) | C/C++程序员之家

    Linux UDP socket编程(UDP通讯模型): UDPClient + UDPService. Linux下大多数网络程序都是基于TCP的,很少基于UDP,简单的通讯模型如下,开发时候备用! ...

  6. C#UDP通讯UdpClient

    目录(?)[+] 遇到如下两个问题 远程主机强迫关闭了一个现有的连接的错误 [html] view plaincopy print? class UdpClientClass { /// <su ...

  7. UDP 通讯协议 局域网通信发送消息 简单实现

    发送端 import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; imp ...

  8. socket之UDP通讯

    该文章简单的讲解linux中socket UDP通讯 UDP(user datagram protocol)的中文叫用户数据报协议,属于传输层.UDP是面向非连接的协议,它不与对方建立连接,而是直接把 ...

  9. Java UDP通讯的简单实现

    UDP协议: 基于TCP协议可以建立稳定连接的点对点的通信.这种通信方式实时.快速.安全性高,但是很占用系统的资源. 在网络传输方式上,还有另一种基于UDP协议的通信方式,称为数据报通信方式.在这种方 ...

最新文章

  1. 余弦相似和内积的意义? 区别
  2. c语言语系的命名风格和java系命名风格
  3. 一览群智胡健:在中国完全照搬Palantir模式,这不现实
  4. 她破解哈希函数算法:坚持10年做一件事一定能做成
  5. 在网络推广外包中企业网站排名优化在网络推广外包中如何实现?
  6. python时间序列预测报错_python如何做时间序列
  7. LeetCode Hot100 ---- 滑动窗口专题
  8. 这个夏天,感动我的歌,感动我的你
  9. 我的blog开张了,希望大家能多多赏光啊
  10. android applybatch,android – 使用applyBatch插入成千上万的联系人条目很慢
  11. java与python反转Ture与False的方法
  12. AWS 聘用 Rust 编译器联合创始人,大企为何都爱 Rust?
  13. C/C++[PAT B1022]D进制的A+B
  14. 专家教你简单又轻松的MD5解密方法,一看就会
  15. Axure RP 8 最新注册码
  16. 【无标题】C# 修改操作时禁用过滤器
  17. PCIe总线的参考时钟与同步时钟的差异
  18. 像素值/DN值/数字量化值
  19. 什么是前后端分离技术?
  20. 软件工程的6个阶段以及成果精简版

热门文章

  1. 如何在 Google Chrome 浏览器中使用 Java?
  2. echarts 仪表盘
  3. 菜菜子随笔:今年的第一抹桂花香
  4. php 银行支付通道_接口--php对接农行网上支付平台-b2b
  5. 高斯型随机粗糙面MATLAB仿真
  6. 制作CPA静默安装包和静默包软件捆绑方法
  7. 超过百万的数组——解决方法
  8. [*CTF2019]She buuctf
  9. GPS秒转北京时间(年月日时分秒)+ gps 周、周内秒转gps时间戳(单位秒) C++ 代码
  10. oracle有索引的集合,oracle中记录和集合