Dart Protobuf 用法简介
简单记录下如何在 Dart 中使用 Protobuf。
参考
注意点:
- Protobuf 编译器依赖独立安装的Dart 插件来生成 Dart 代码 参考来源
- Dart 要求 Protobuf 编译器版本为 3.0.0 及以上 参考来源
- Dart 只支持 proto3 scheme 参考来源
Dart 只支持 proto2 scheme 参考来源
安装和编译
第一步,安装 Protobuf 编译器。可以从 Protobuf release 页面下载和安装,也可以 brew install protobuf
安装。
第二步,安装 Protobuf Dart 插件。
- 下载代码。
git clone https://github.com/dart-lang/protobuf.git
- 编译插件。调用
pub install
编译插件,编译后源码bin
目录下可以找到proto-gen-dart
文件。如果出错,可以使用pub --trace install
查看详细错误日志 - 使用插件。将插件配置到 PATH 路径中,或者调用
protoc
时使用--plugin
参数指定插件路径
第三步,运行 protoc 编译生成 .proto.dart
文件。
1 | ➜ aproj_pub_proj git:(cm) ✗ protoc --proto_path=proto --dart_out=build/gen --plugin=/Users/xxx/Documents/GitHub/protobuf/protoc_plugin/bin proto/aproj/comm_conn.proto |
- 第一次出错是因为
--plugin
指定的 Dart 插件路径不正确,应当指定具体文件而不是文件所在的目录 - 第二次出错是因为 Dart 插件依赖
dart
命令,要确保 PATH 中有配置dart
。
PATH 中配置 dart
命令方法如下:
1 | export DART_PATH="$HOME/flutter/bin/cache/dart-sdk/bin" |
编译成功!
发送字符串
先使用 Dart 实现简单的服务器端 SimpleServer
和客户端 SimpleClient
,代码分别如下。
SimpleServer
收到客户端发送的数据,转换成大写的 UTF-8 后发回客户端,并关闭 Socket。
1 | import 'dart:convert'; |
SimpleClient
向服务器端发送 ‘hello’,并且接收和输出服务器端的响应。
1 | import 'dart:async'; |
发送 Protobuf 数据
如何在使用 Protobuf 数据在 SimpleServer
和 SimpleClient
之间通信?
注意,生成的 .pb.dart
文件中有如下 import
:
1 | import 'package:fixnum/fixnum.dart'; |
所以相应地需要在 pubspec.yaml
中添加对应的依赖。
第一步,为工程添加 fixnum
和 protobuf 依赖。添加后记得运行 flutter pb get
同步一下。
1 | dependencies: |
第二步,将生成的 .pb.dart
文件拷贝到工程,供 SimpleServer
和 SimpleClient
引用。
第三步,修改服务器端 SimpleServer
和客户端 SimpleClient
代码,使用 Protobuf 通信。修改后的代码分别如下:
SimpleServer
收到客户端发送的 Protobuf 数据并以 JSON 格式打印出来,然后向客户端发送 Protobuf 数据 CommRsp
,最后关闭 Socket。
1 | import 'dart:io'; |
SimpleClient
向服务器端发送 Protobuf 数据 CommReq
,并且接收和打印服务器端的响应。
1 | import 'dart:io'; |
注意以下两点:
- 注意 Protobuf 数据字段分为 required 字段和 optional 字段
- 使用
socket.add()
发送数据而不是socket.write()
。注意socket.write()
先对要发送的数据编码后再调用socket.add()
,实际发送的是编码后的数据
1 | void write(Object obj) { |
如何在 Dart 中创建和解析 Protobuf 数据,请参考官方文档。