当前位置:网站首页>Basic usage of protobuf
Basic usage of protobuf
2022-07-26 09:58:00 【_ Soren】
List of articles
protobuf Installation configuration
protobuf(protocol buffer) yes google A data exchange format of , It is independent of the platform language .
google Provides protobuf Multilingual implementation :java、c#、c++、go and python, Each implementation contains the compiler and library files of the corresponding language .
Because it's a binary format , Than using xml(20 times ) 、json(10 times ) Data exchange is much faster . It can be used for data communication between distributed applications or data exchange in heterogeneous environment . As a binary data transmission format with excellent efficiency and compatibility , Can be used for such as network transmission 、 The configuration file 、 Data storage and many other fields .
stay github Source code download address :https://github.com/google/protobuf
1、 Decompress the package :unzip protobuf-master.zip
2、 Enter the unzipped folder :cd protobuf-master
3、 Install the required tools :sudo apt-get install autoconf automake libtool curl make g++ unzip
4、 Automatic generation configure The configuration file :./autogen.sh
5、 Configuration environment :./configure
6、 Compiled source code ( It takes a long time ):make
7、 install :sudo make install
8、 Refresh dynamic library :sudo ldconfig
protobuf Preparation of configuration file
Example :
The suffix of the configuration file is .proto, Define the message type in the following format .
syntax = "proto3"; // The statement protobuf Version of
package fixbug; // Declare the package where the code is located ( about C++ It is namespace)
// Login message type
message LoginRequest
{
string name = 1; // 1 Represents the first field
string pwd = 2;
}
// Define the login response message type
message LoginResponse
{
int32 errcode = 1;
string errmsg = 2;
bool success = 3;
}
Compile command :
First use the command protoc You can view the prompt commands

Here you can see , Which language header file and source file do you want to generate , There are corresponding commands 
Use command :./ It indicates that... Is generated in the current directory
protoc test.proto --cpp_out=./


Examples of use
serialize
Use the just compiled test.pb.h The type in
#include <iostream>
#include <string>
#include "test.pb.h"
using namespace fixbug;
int main(void)
{
// Encapsulates the Login Request the information of the object
LoginRequest req;
req.set_name("zhang san");
req.set_pwd("123456");
// Object data serialization
std::string send_str;
if (req.SerializeToString(&send_str))
{
std::cout << send_str.c_str() << std::endl;
}
return 0;
}


Deserialization
#include <iostream>
#include <string>
#include "test.pb.h"
using namespace fixbug;
int main(void)
{
// Encapsulates the Login Request the information of the object
LoginRequest req;
req.set_name("zhang san");
req.set_pwd("123456");
// Object data serialization
std::string send_str;
if (req.SerializeToString(&send_str))
{
std::cout << send_str.c_str() << std::endl;
}
// from send_str Deserialize a login object
LoginRequest req2;
if (req2.ParseFromString(send_str))
{
std::cout << req2.name() << std::endl;
std::cout << req2.pwd() << std::endl;
}
return 0;
}

Use experience
generally speaking , stay protobuf The string type will be set to bytes type
// Login message type
message LoginRequest
{
bytes name = 1; // 1 Represents the first field
bytes pwd = 2;
}
If there is repeated code in the writing process , You can take out the repetition and write it as a message.
Example , stay LoginResponse and GetFriendListsResponse There are errcode Fields and errmsg Field , You can write these two duplicate fields as one message, Use this type in two other places .
message ResoultCode
{
int32 errcode = 1;
bytes errmsg = 2;
}
// Login message type
message LoginRequest
{
bytes name = 1; // 1 Represents the first field
bytes pwd = 2;
}
// Define the login response message type
message LoginResponse
{
ResoultCode resoult = 1;
bool success = 3;
}
message GetFriendListsRequest
{
uint32 userid = 1;
}
message GetFriendListsResponse
{
ResoultCode resoult = 1;
}
protobuf List creation
In the example above , What is written is a common data type ,protobuf In addition to data objects , There are also lists and mapping tables .
as follows , Want to get a user's friend information , After defining your friend information , Again GetFriendListsResponse Define the friend list field in , You need to use keywords repeated.
syntax = "proto3"; // The statement protobuf Version of
package fixbug; // Declare the package where the code is located ( about C++ It is namespace)
message ResoultCode
{
int32 errcode = 1;
bytes errmsg = 2;
}
// Login message type
message LoginRequest
{
bytes name = 1; // 1 Represents the first field
bytes pwd = 2;
}
// Define the login response message type
message LoginResponse
{
ResoultCode resoult = 1;
bool success = 3;
}
message GetFriendListsRequest
{
uint32 userid = 1;
}
message User
{
bytes name = 1;
uint32 age = 2;
enum Sex
{
MAN = 0;
WOMAN = 1;
}
Sex sex = 3;
}
message GetFriendListsResponse
{
ResoultCode resoult = 1;
repeated User friend_list = 2; // List the type
}
Examples of use :
#include <iostream>
#include <string>
#include "test.pb.h"
using namespace fixbug;
int main(void)
{
GetFriendListsResponse rsp;
ResultCode* rc = rsp.mutable_result();
rc->set_errcode(0);
User* user1 = rsp.add_friend_list();
user1->set_name("zhang san");
user1->set_age(20);
user1->set_sex(User::MAN);
User* user2 = rsp.add_friend_list();
user2->set_name("li si");
user2->set_age(21);
user2->set_sex(User::MAN);
std::cout << rsp.friend_list_size() << std::endl;
return 0;
}

If you want to output the information of your friends , It's also very simple. ,friend_list() Back to a User type , So use this type to receive .
Code :
#include <iostream>
#include <string>
#include "test.pb.h"
using namespace fixbug;
int main(void)
{
GetFriendListsResponse rsp;
ResultCode* rc = rsp.mutable_result();
rc->set_errcode(0);
User* user1 = rsp.add_friend_list();
user1->set_name("zhang san");
user1->set_age(20);
user1->set_sex(User::MAN);
User* user2 = rsp.add_friend_list();
user2->set_name("li si");
user2->set_age(21);
user2->set_sex(User::MAN);
std::cout << rsp.friend_list_size() << std::endl;
User friend1 = rsp.friend_list(0);
User friend2 = rsp.friend_list(1);
std::cout << friend1.name() << std::endl;
std::cout << friend1.age() << std::endl;
std::cout << friend1.sex() << std::endl;
std::cout << friend2.name() << std::endl;
std::cout << friend2.age() << std::endl;
std::cout << friend2.sex() << std::endl;
return 0;
}

If a member of a data object is still an object , You need to receive a with a pointer mutable The address of .

Definition description RPC Type of method -service
stay protobuf in , Default does not generate service Service type , Need to add a option Options .
// Define this option , To generate service Service class and RPC Methods described , Default does not generate
option cc_generic_services = true;
According to the configuration file written above , It can be learned that service Service classes can be written like this :
// stay protobuf How to define and describe rpc Type of method - service
service UserServiceRpc
{
rpc Login(LoginRequest) returns(LoginResponse);
rpc GetFriendLists(GetFriendListsRequest) returns(GetFriendListsResponse);
}
Generate code rules
Then it generates C++ What does the code look like ?
With LoginRequest For example : It's a class class , Inherited from google::protobuf::Message


Again ,request It's also class class , Inherit Message
Icon :

So it's written service The code generated by type is as follows :
You can find , Generated classes and written rpc The method is consistent . The generated class is
Callee ServiceProvider rpc Service providers
class UserServiceRpc_Stub;
class UserServiceRpc : public ::PROTOBUF_NAMESPACE_ID::Service {
protected:
// This class should be treated as an abstract interface.
inline UserServiceRpc() {
};
public:
virtual ~UserServiceRpc();
typedef UserServiceRpc_Stub Stub;
static const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* descriptor();
virtual void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::LoginRequest* request,
::fixbug::LoginResponse* response,
::google::protobuf::Closure* done);
virtual void GetFriendLists(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::GetFriendListsRequest* request,
::fixbug::GetFriendListsResponse* response,
::google::protobuf::Closure* done);
// implements Service ----------------------------------------------
const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor* GetDescriptor();
/* Other content */
};
The second one is stub
caller ServiceConsumer rpc Serving consumers
class UserServiceRpc_Stub : public UserServiceRpc {
public:
UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel);
UserServiceRpc_Stub(::PROTOBUF_NAMESPACE_ID::RpcChannel* channel,
::PROTOBUF_NAMESPACE_ID::Service::ChannelOwnership ownership);
~UserServiceRpc_Stub();
inline ::PROTOBUF_NAMESPACE_ID::RpcChannel* channel() {
return channel_; }
// implements UserServiceRpc ------------------------------------------
void Login(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::LoginRequest* request,
::fixbug::LoginResponse* response,
::google::protobuf::Closure* done);
void GetFriendLists(::PROTOBUF_NAMESPACE_ID::RpcController* controller,
const ::fixbug::GetFriendListsRequest* request,
::fixbug::GetFriendListsResponse* response,
::google::protobuf::Closure* done);
private:
::PROTOBUF_NAMESPACE_ID::RpcChannel* channel_;
bool owns_channel_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UserServiceRpc_Stub);
};
Note that the constructor of this class needs to pass in a Channel type , This type is an abstract base class :
class PROTOBUF_EXPORT RpcChannel {
public:
inline RpcChannel() {
}
virtual ~RpcChannel();
// Call the given method of the remote service. The signature of this
// procedure looks the same as Service::CallMethod(), but the requirements
// are less strict in one important way: the request and response objects
// need not be of any specific class as long as their descriptors are
// method->input_type() and method->output_type().
virtual void CallMethod(const MethodDescriptor* method,
RpcController* controller, const Message* request,
Message* response, Closure* done) = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
};
So for the above example , Calling Login() Method or GetFriendLists() When the method is used , At the bottom, it will be called
channel_->CallMethod()
This method is a pure virtual function , Need derived class inheritance RpcChannel Class, override the method ( Because the base class pointer can point to the derived class object , So the method called will be implemented by derived classes CallMethod() Method ).
Icon :

边栏推荐
- A new paradigm of distributed deep learning programming: Global tensor
- [MySQL database] a collection of basic MySQL operations - the basis of seeing (adding, deleting, modifying, and querying)
- PMM (percona monitoring and management) installation record
- 网络流学习笔记
- PHP executes shell script
- IE7 set overflow attribute failure solution
- 在.NET 6.0中配置WebHostBuilder
- Sqoop【付诸实践 02】Sqoop1最新版 全库导入 + 数据过滤 + 字段类型支持 说明及举例代码(query参数及字段类型强制转换)
- Wechat applet development
- copyTo
猜你喜欢

面试突击68:为什么 TCP 需要 3 次握手?

新增市场竞争激烈,中国移动被迫推出限制性超低价5G套餐

解决npm -v突然失效 无反应

MQTT X CLI 正式发布:强大易用的 MQTT 5.0 命令行工具

2022 zhongkepan cloud - server internal information acquisition and analysis flag

Node 内存溢出及V8垃圾回收机制

The problem of accessing certsrv after configuring ADCs

Due to fierce competition in the new market, China Mobile was forced to launch a restrictive ultra-low price 5g package

QT handy notes (III) use qtcharts to draw a line chart in VS

2022年中科磐云——服务器内部信息获取 解析flag
随机推荐
PHP one-time request lifecycle
Interview shock 68: why does TCP need three handshakes?
服务器内存故障预测居然可以这样做!
The diagram of user login verification process is well written!
Vectortilelayer replacement style
Keeping alive to realize MySQL automatic failover
E. Two Small Strings
Azkaban【基础知识 01】核心概念+特点+Web界面+架构+Job类型(一篇即可入门Azkaban工作流调度系统)
Principle analysis and source code interpretation of service discovery
莫队学习笔记(一)
Li Kou - binary tree pruning
Fuzzy PID control of motor speed
PHP executes shell script
2021 windows penetration of "Cyberspace Security" B module of Shandong secondary vocational group (analysis)
云原生(三十六) | Kubernetes篇之Harbor入门和安装
Usage of the formatter attribute of El table
Use of selectors
Azkaban [basic knowledge 01] core concepts + features +web interface + Architecture +job type (you can get started with Azkaban workflow scheduling system in one article)
Draw arrows with openlayer
服务发现原理分析与源码解读