分布式网络通信框架(三)——protobuf使用案例

例子1

test.proto文件如下:

syntax = "proto3"; // 声明了protobuf版本

package fixbug; // 声明了代码所在的包(生成C++代码后就是namespace 名字)

// 定义登录消息类型
message LoginRequest
{
    string name = 1; // =1 代表name是这个message第一个字段,不是指name的值
    string pwd = 2;
}

// 定义登录响应消息
message LoginResponse
{
    int32 errcode = 1;
    string errmsg = 2;
    bool success = 3;
}

对proto文件进行编译:

protoc test.proto --cpp_out=./

产生两个cpp文件

在这里插入图片描述

测试代码main.cc如下:

#include "test.pb.h"
#include <iostream>
#include <string>
using namespace fixbug; // 工作中不要这样!!防止命名空间污染

int main()
{
    // 封装login请求对象的数据
    LoginRequest req;
    req.set_name("lisi");
    req.set_pwd("123456");

    std::string send_str;
    // 将成员值序列化为字符串
    if(req.SerializeToString(&send_str))
    {
        std::cout << send_str.c_str() << std::endl;
    }

    // 从send_str反序列化一个login请求对象
    LoginRequest reqB;
    if(reqB.ParseFromString(send_str))
    {
        std::cout << reqB.name() << std::endl;
        std::cout << reqB.pwd() << std::endl;
    }

    return 0;
}
jyhlinux@ubuntu:~/share/mprpc/test/protobuf$ g++ main.cc test.pb.cc -o main -lprotobuf -L/usr/local/lib
jyhlinux@ubuntu:~/share/mprpc/test/protobuf$ ./main

实验结果

lisi123456

lisi

123456

注意

建议将string类型替换为bytes类型,因为bytes直接存二进制文件,效率更高一点,如果用string,最后还要将其转换为字节数据,而bytes则不需要。最后结果和上面相同

syntax = "proto3"; // 声明了protobuf版本

package fixbug; // 声明了代码所在的包(生成C++代码后就是namespace 名字)

// 定义登录消息类型
message LoginRequest
{
    bytes name = 1; // =1 代表name是这个message第一个字段,不是指name的值
    bytes pwd = 2;
}

// 定义登录响应消息
message LoginResponse
{
    int32 errcode = 1;
    bytes errmsg = 2;
    bool success = 3;
}

例子2——列表

protobuf文件test.proto

列表需要在遍变量声明前加repeated

syntax = "proto3"; // 声明了protobuf版本

package fixbug; // 声明了代码所在的包(生成C++代码后就是namespace 名字)

message ResultCode
{
    int32 errcode = 1;
    bytes errmsg = 2;
}

// 定义登录消息类型
message LoginRequest
{
    bytes name = 1; // =1 代表name是这个message第一个字段,不是指name的值
    bytes pwd = 2;
}

// 定义登录响应消息
message LoginResponse
{
    ResultCode result = 1;
    bool success = 3;
}

message GetFriendListRequest
{
    uint32 userid = 1;
}

message User
{
    bytes name =1;
    uint32 age = 2;
    enum Sex
    {
        MAN = 0;
        WOMAN = 1;
    }
    Sex sex = 3;
}

message GetFriendListResponse
{
    ResultCode result = 1;
    repeated User friend_list = 2; // repeated表示列表类型!!!
}

测试源代码 main.cc

#include "test.pb.h"
#include <iostream>
#include <string>
using namespace fixbug; // 工作中不要这样!!防止命名空间污染

int main()
{
    // LoginResponse rsp;
    // // 对象成员的修改方法,要先获取成员的指针
    // ResultCode *rc = rsp.mutable_result();
    // rc->set_errcode(1);
    // rc->set_errmsg("登录失败");

    GetFriendListResponse rsp;
    ResultCode *rc = rsp.mutable_result();
    rc->set_errcode(0);
   
    User *user1 = rsp.add_friend_list(); // 返回一个指向User类型指针,我们往里填数据就是在新的位置加入元素了
    user1->set_name("zhangsan");
    user1->set_age(20);
    user1->set_sex(User::MAN);

    User *user2 = rsp.add_friend_list(); // 返回一个指向User类型指针,我们往里填数据就是在新的位置加入元素了
    user2->set_name("lisi");
    user2->set_age(21);
    user2->set_sex(User::MAN);

    //std::cout << rsp.friend_list_size() << std::endl;

    // 打印列表元素
    int n = rsp.friend_list_size();
    for(int i = 0; i < n; ++i)
    {
        std::cout << rsp.friend_list(i).name() << " "<< rsp.friend_list(i).age() << " " << rsp.friend_list(i).sex() << std::endl;
    }
    return 0;
}

编译执行

jyhlinux@ubuntu:~/share/mprpc/test/protobuf$ protoc test.proto  --cpp_out=./
jyhlinux@ubuntu:~/share/mprpc/test/protobuf$ g++ main.cc test.pb.cc -o main -lprotobuf -L/usr/local/lib
jyhlinux@ubuntu:~/share/mprpc/test/protobuf$ ./main 

执行结果

zhangsan 20 0

lisi 21 0

例子3——定义方法类型(用于描述rpc方法)的成员

下面的例子使用service 关键字定义描述rpc方法的类型,并且注意开头要设置option

syntax = "proto3"; // 声明了protobuf版本

package fixbug; // 声明了代码所在的包(生成C++代码后就是namespace 名字)

// 定义下面的选项,表示生成service服务类和rpc方法描述,默认不生成
option cc_generic_services = true;

message ResultCode
{
    int32 errcode = 1;
    bytes errmsg = 2;
}

// 定义登录消息类型
message LoginRequest
{
    bytes name = 1; // =1 代表name是这个message第一个字段,不是指name的值
    bytes pwd = 2;
}

// 定义登录响应消息
message LoginResponse
{
    ResultCode result = 1;
    bool success = 3;
}

message GetFriendListRequest
{
    uint32 userid = 1;
}

message User
{
    bytes name =1;
    uint32 age = 2;
    enum Sex
    {
        MAN = 0;
        WOMAN = 1;
    }
    Sex sex = 3;
}

message GetFriendListResponse
{
    ResultCode result = 1;
    repeated User friend_list = 2; // repeated表示列表类型
}

// 在protobuf里定义描述rpc方法的类型
service UserServiceRpc
{
    rpc Login(LoginRequest) returns(LoginResponse);
    rpc GetFriendList(GetFriendListRequest) returns(GetFriendListResponse);
}

通过protoc会生成的UserServiceRpc类(服务提供方使用)和 UserServiceRpc_Stub类(服务调用方使用)

在这里插入图片描述

这也是ServiceProvider,即rpc服务提供者。

UserServiceRpc_Stub类是服务消费者即serviceConsumer

在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
protobuf(Protocol Buffers)是一种用于序列化结构化数据的语言无关、平台无关、可扩展的机制。它可以用于网络消息协议的设计。下面将介绍protobuf作为网络消息协议的优点。 首先,protobuf具有良好的性能。相比于其他序列化机制,protobuf具有更高的效率和更小的数据体积。因为protobuf使用二进制编码,并且采用紧凑的数据格式,所以在网络传输过程中能够更快地进行数据传输,减少带宽占用和网络资源消耗。 其次,protobuf具有良好的跨语言支持。因为protobuf使用IDL(Interface Definition Language)来定义消息结构,它能够生成多种语言的代码,包括C++, Java, Python等。这样,不同语言的服务端和客户端可以通过protobuf定义的消息结构进行通信,实现跨平台、跨语言的消息传递。 此外,protobuf还具有可扩展性。当需求变化时,可以很方便地通过更新消息结构来支持新的数据类型或字段,而无需改变底层的网络通信协议。 protobuf支持向后和向前兼容,可以确保客户端和服务端的平滑升级。 另外,protobuf还支持消息的压缩和加密,以提高数据传输的安全性和效率。通过使用压缩算法和加密算法,可以减少消息的大小,并保护数据的机密性。 综上所述,protobuf作为网络消息协议具有较高的性能、良好的跨语言支持、可扩展性和安全性等优点。因此,使用protobuf作为网络消息协议可以提高数据传输的效率和安全性,并实现跨平台、跨语言的消息通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值