protobuf的基本类型和默认值,python中的小坑

标量数值类型

标量消息字段可以具有以下类型之一——该表显示了。原型文件,以及自动生成类中的对应类型:

默认值

python操作的坑

  1. 目录结构

  2. helloworld.proto
syntax = "proto3";

option go_package = "../proto;";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
} message HelloRequest {
string name = 1;
repeated int32 id = 2;
} message HelloReply {
string message = 1;
}

切换到proto目录下,执行命令 python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. helloworld.proto

3. server.py

from concurrent.futures import ThreadPoolExecutor

import grpc

from grpc_hello.proto import helloworld_pb2_grpc, helloworld_pb2

class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message=f"你好, [name: {request.name}, id: {request.id}]") if __name__ == '__main__':
# 1. 实例化server
server = grpc.server(ThreadPoolExecutor(max_workers=10))
# 2. 注册逻辑到server中
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
# 3. 运行server
server.add_insecure_port("127.0.0.1:50051")
server.start()
# 主线程等待所有子线程
server.wait_for_termination()
  1. client.py
import grpc

from grpc_hello.proto import helloworld_pb2, helloworld_pb2_grpc

if __name__ == '__main__':
with grpc.insecure_channel("127.0.0.1:50051") as channel:
greeter = helloworld_pb2_grpc.GreeterStub(channel)
# 方法一:
"""
hello_request = helloworld_pb2.HelloRequest(
name="张三",
id=[1, 22, 33],
)
"""
# 方法二:
hello_request = helloworld_pb2.HelloRequest()
hello_request.name = "李四"
# 此处就是python操作时的坑所在,不能直接等于,因为创建实例时已经对id初始化了
hello_request.id.extend([11, 22, 33])
hello_request.id.append(44)
rsp: helloworld_pb2.HelloReply = greeter.SayHello(hello_request) print(rsp.message)

option go_package的作用

option go_package = "../proto;proto";

第一个分号前面的代表生成的pb文件保存的目录路径,第一个分号后面的代表包名称

当proto文件不同步的时候容易出现的问题

go的客户端和服务端

  1. client.go
点击查看代码
package main

import (
"context"
"fmt"
"goRPC/grpc_proto_test/proto"
"google.golang.org/grpc"
"log" ) func main() {
// 创建链接
clientConn, err := grpc.Dial("127.0.0.1:50053", grpc.WithInsecure())
if err != nil {
log.Fatalf("链接失败, %s\n", err.Error())
}
defer clientConn.Close()
// 声明客户端
client := proto.NewGreeterClient(clientConn)
// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
}) fmt.Println(helloReplay.Message)
}

2. server.go

点击查看代码
package main

import (
"context"
"fmt"
"goRPC/grpc_proto_test/proto"
"google.golang.org/grpc"
"log"
"net"
) type Greeter struct{} func (g *Greeter) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply, error) {
return &proto.HelloReply{
Message: fmt.Sprintf("hello name: %s, url: %s", request.Name, request.Url),
}, nil
} func main() {
// 实例化一个server
server := grpc.NewServer() // 注册逻辑到server中
proto.RegisterGreeterServer(server, &Greeter{}) // 启动server
listener, err := net.Listen("tcp", "127.0.0.1:50053")
if err != nil {
log.Fatalln(err.Error())
}
server.Serve(listener) }

python的客户端和服务端

  1. client.py
点击查看代码
import grpc

from proto import hello_pb2, hello_pb2_grpc

if __name__ == '__main__':
# 链接server
with grpc.insecure_channel("127.0.0.1:50053") as channel:
greeter = hello_pb2_grpc.GreeterStub(channel)
rsp = greeter.SayHello(hello_pb2.HelloRequest(name="马艳娜", url="https://mayanan.cn")) print(rsp.message)
  1. server.py
点击查看代码
from concurrent.futures import ThreadPoolExecutor

import grpc

from proto import hello_pb2, hello_pb2_grpc

class Greeter(hello_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return hello_pb2.HelloReply(message=f"hello 姓名:{request.name} url: {request.url}") if __name__ == '__main__':
# 实例化server
server = grpc.server(ThreadPoolExecutor(max_workers=10)) # 注册逻辑到server中
hello_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) # 启动server
server.add_insecure_port("127.0.0.1:50053")
server.start()
server.wait_for_termination()

proto文件中引入其它的proto文件

  1. base.proto文件
syntax = "proto3";

message Pong {
string id = 1;
}
  1. hello.proto文件
syntax = "proto3";

import "Lib/site-packages/grpc_tools/_proto/google/protobuf/empty.proto";
import "base.proto"; option go_package = "../proto;proto"; service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc Ping(google.protobuf.Empty) returns (Pong);
} message HelloRequest {
string name = 1;
string url = 2;
}
message HelloReply {
string message = 1;
}

嵌套的message对象

python中的用法

  1. base.proto
syntax = "proto3";

message Pong {
string id = 1;
}
  1. hello.proto文件
点击查看代码
syntax = "proto3";

import "google/protobuf/empty.proto";
import "base.proto"; option go_package = "../proto;proto"; service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc Ping(google.protobuf.Empty) returns (Pong);
} message HelloRequest {
string name = 1;
string url = 2;
}
message HelloReply {
string message = 1; // 嵌套的message对象
message Result {
string name = 1;
string url = 2;
} repeated Result data = 2;
}

3. server.py

点击查看代码
from concurrent.futures import ThreadPoolExecutor

import grpc

from proto import hello_pb2, hello_pb2_grpc
from google.protobuf.empty_pb2 import Empty
from proto.base_pb2 import Pong result = hello_pb2.HelloReply.Result()
pong = hello_pb2.base__pb2.Pong()
empty = hello_pb2.google_dot_protobuf_dot_empty__pb2.Empty()

go中的用法

  1. base.proto
syntax = "proto3";
option go_package = "../proto;proto"; message Empty {}
message Pong {
string id = 1;
}
  1. hello.proto
点击查看代码
syntax = "proto3";

import "base.proto";

option go_package = "../proto;proto";

service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc Ping(Empty) returns (Pong);
} message HelloRequest {
string name = 1;
string url = 2;
}
message HelloReply {
string message = 1; // 嵌套的message对象
message Result {
string name = 1;
string url = 2;
} repeated Result data = 2;
}
  1. client.go
result := proto.HelloReply_Result{}
pong := proto.Pong{}
empty := proto.Empty{}
fmt.Println(result, pong, empty)

protobuf中的enum枚举类型

  1. 枚举类型定义
enum Gender {
MALE = 0;
FEMALE = 1;
} message HelloRequest {
string name = 1;
string url = 2;
Gender g = 3;
}
  1. 枚举类型使用
	// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto_bak.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
G: proto_bak.Gender_MALE,
})

protobuf中的map类型

  1. map类型的定义
message HelloRequest {
string name = 1;
string url = 2;
Gender g = 3;
map <string, string> mp = 4;
}
  1. map类型的使用
	// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto_bak.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
G: proto_bak.Gender_MALE,
Mp: map[string]string{"name2": "李四", "age": "28"},
})

protobuf内置的timestamp类型

  1. 将protoc中的include目录复制到当前项目proto_bak目录下,然后导入timestamp.proto文件,定义时间戳类型
点击查看代码
syntax = "proto3";

import "include/google/protobuf/timestamp.proto";

option go_package = "../proto_bak;proto_bak";

service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
} enum Gender {
MALE = 0;
FEMALE = 1;
} message HelloRequest {
string name = 1;
string url = 2;
Gender g = 3;
map <string, string> mp = 4;
google.protobuf.Timestamp addTime = 5;
} message HelloReply {
string message = 1;
}
  1. go代码中使用proto中的时间戳类型
点击查看代码
package main

import (
"context"
"fmt"
"goRPC/grpc_proto_test/proto_bak"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/timestamppb"
"log"
"time"
) func main() {
// 创建链接
clientConn, err := grpc.Dial("127.0.0.1:50053", grpc.WithInsecure())
if err != nil {
log.Fatalf("链接失败, %s\n", err.Error())
}
defer clientConn.Close()
// 声明客户端
client := proto_bak.NewGreeterClient(clientConn)
// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto_bak.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
G: proto_bak.Gender_MALE,
Mp: map[string]string{"name2": "李四", "age": "28"},
AddTime: timestamppb.New(time.Now()),
}) fmt.Println(helloReplay.Message)
}

至此,protobuf大致讲解完毕。

protobuf详解的更多相关文章

  1. 通讯协议序列化解读(一) Protobuf详解教程

    前言:说到JSON可能大家很熟悉,是目前应用最广泛的一种序列化格式,它使用起来简单方便,而且拥有超高的可读性.但是在越来越多的应用场景里,JSON冗长的缺点导致它并不是一种最优的选择. 一.常用序列化 ...

  2. grpc系列- protobuf详解

    Protocol Buffers 是一种与语言.平台无关,可扩展的序列化结构化数据的方法,常用于通信协议,数据存储等等.相较于 JSON.XML,它更小.更快.更简单,因此也更受开发人员的青眯. 基本 ...

  3. Protocol Buffers编码详解,例子,图解

    Protocol Buffers编码详解,例子,图解 本文不是让你掌握protobuf的使用,而是以超级细致的例子的方式分析protobuf的编码设计.通过此文你可以了解protobuf的数据压缩能力 ...

  4. Protobuf 文件生成工具 Prototool 命令详解

    Protobuf 文件生成工具 Prototool 命令详解 简介 Prototool 是 Protobuf 文件的生成工具, 目前支持go, php, java, c#, object c 五种语言 ...

  5. ProtoBuf格式详解

    - 数据结构 通过前面的例子,可以看到PB的数据结构就是每项数据独立编码,包含一个表示数据类型 - Varint Varint是一种对数字进行编码的方法,将数字编码成不定长的二进制数据,数值越小,编码 ...

  6. 理论经典:TCP协议的3次握手与4次挥手过程详解

    1.前言 尽管TCP和UDP都使用相同的网络层(IP),TCP却向应用层提供与UDP完全不同的服务.TCP提供一种面向连接的.可靠的字节流服务. 面向连接意味着两个使用TCP的应用(通常是一个客户和一 ...

  7. Protocol Buffer技术详解(Java实例)

    Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发 ...

  8. Protocol Buffer技术详解(C++实例)

    Protocol Buffer技术详解(C++实例) 这篇Blog仍然是以Google的官方文档为主线,代码实例则完全取自于我们正在开发的一个Demo项目,通过前一段时间的尝试,感觉这种结合的方式比较 ...

  9. Redis协议详解

    smark Beetle可靠.高性能的.Net Socket Tcp通讯组件 支持flash amf3,protobuf,Silverlight,windows phone Redis协议详解 由于前 ...

随机推荐

  1. c++基础之虚函数表指针和虚函数表创建时机

    虚函数表指针 虚函数表指针随对象走,它发生在对象运行期,当对象创建的时候,虚函数表表指针位于该对象所在内存的最前面. 使用虚函数时,虚函数表指针指向虚函数表中的函数地址即可实现多态. 虚函数表 虚函数 ...

  2. 【LeetCode】19. Remove Nth Node From End of List 删除链表的倒数第 N 个结点

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:链表, 删除节点,双指针,题解,leetcode, 力扣 ...

  3. 1114. Boxes

    1114. Boxes Time limit: 0.6 secondMemory limit: 64 MB N boxes are lined up in a sequence (1 ≤ N ≤ 20 ...

  4. 海康威视摄像机Java SDK拉流(二)开启关闭实时预览

    本篇介绍海康威视摄像机通过SDK开启关闭实时预览接口 下篇介绍实时预览的回调函数及解码库 测试环境: 系统:Centos 7 SDK:设备网络SDK Linux64 实时预览模块流程: 图中虚线框部分 ...

  5. Bristol大学密码学博士生的五十二个知识点

    Bristol大学密码学博士生的五十二个知识点 这个系列,是Bristol大学的密码安全工作组为密码学和信息安全相关的博士准备了52个基本知识点. 原地址:http://bristolcrypto.b ...

  6. Generating Adversarial Examples with Adversarial Networks

    目录 概 主要内容 black-box 拓展 Xiao C, Li B, Zhu J, et al. Generating Adversarial Examples with Adversarial ...

  7. CS5265typec转HDMI2.0方案说明书|Capstone CS5265typec转HDMI4K60HZ单转电路|瑞奇达CS5265typec拓展坞设计

    一.CS5265总概 Capstone CS5265 USB Type-C到HDMI转换器结合了USB Type-C输入接口和数字高清多媒体接口(HDMI)输出.嵌入式微控制器(MCU)基于工业标准8 ...

  8. .net core中EFCore发出警告:More than twenty 'IServiceProvider' instances have been created for internal use by Entity Framework

    最近使用.net core k开发时,碰到个问题,Ef使用中程序发出了一个警告: More than twenty 'IServiceProvider' instances have been cre ...

  9. 访问局域网内其他主机的VMware虚拟机上的mysql数据库和redis缓存

    上一篇写了访问局域网内其他主机的虚拟机上的项目 ,现在说说访问局域网内其他主机的虚拟机上的数据库和缓存 博主使用的linux是Ubuntu16.04: 一.安装数据库和缓存 这里连接的数据库和缓存以m ...

  10. Pytest_常用执行参数详解(3)

    前面讲了测试用例的执行方式,也认识了 -v  -s 这些参数,那么还有没有其它参数呢?答案肯定是有的,我们可以通过 pytest -h来查看所有可用参数. 从图中可以看出,pytest的参数有很多,但 ...