前言
- 在进入游戏业务编写前,我们还需要了解下数据传输协议
一、Protocuf简介
- Protobuf:Google Protocol Buffer (简称 Protobuf)是google旗下的⼀款轻便⾼效的结构化数据存储格式,平台⽆关、语⾔⽆关、可扩展,可⽤于通讯协议和数据存储等领域。所以很适合⽤做数据存储和作为不同应⽤,不同语⾔之间相互通信的数据交换格式,只要实现相同的协议格式即同⼀ proto⽂件被编译成不同的语⾔版本,加⼊到各⾃的⼯程中去。这样不同语⾔就可以解析其他语⾔通过 protobuf序列化的数据
- 常用的数据交换格式
- json : ⼀般的web项⽬中,最流⾏的主要还是 json。因为浏览器对于json 数据⽀持⾮常好,有很多内建的函数⽀持
- xml : 在 webservice 中应⽤最为⼴泛,但是相⽐于 json,它的数据更加冗余,因为需要成对的闭合标签。json 使⽤了键值对的⽅式,不仅压缩了⼀定的数据空间,同时也具有可读性
- protobuf : 是后起之秀,是⾕歌开源的⼀种数据格式,适合⾼性能,对响应速度有要求的数据传输场景。因为 profobuf 是⼆进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据
- protobuf优势
- 序列化后体积相⽐Json和XML很⼩,适合⽹络传输
- ⽀持跨平台多语⾔
- 消息格式升级和兼容性还不错
- 序列化反序列化速度很快,快于Json的处理速速
- protobuf劣势
- 应⽤不够⼴(相⽐xml和json)
- ⼆进制格式导致可读性差
- 缺乏⾃描述
二、Protobuf环境安装
- 安装步骤
- 安装依赖库:
sudo apt-get install autoconf automake libtool curl make g++ unzip
- 进入goPath目录如:
$justso@justso:/mnt/hgfs/goPath/src
- 下载 protoBuf:
sudo git clone https://github.com/google/protobuf.git
- 进入protobuf目录:
cd protobuf
git config --global --add safe.directory /mnt/hgfs/goPath/src/protobuf
sudo git submodule update --init --recursive
:当使用git clone下来的工程中带有submodule时,初始的时候,submodule的内容并不会自动下载下来的- ⾃动⽣成configure配置⽂件:
./autogen.sh
- 配置环境:
./configure
- 编译源代码(时间⽐较⻓):
make
- make检查(注意虚拟机内存需要8G,否则会报错误FAIL: protobuf-test):
make check
- 安装:
sudo make install
- 刷新共享库 (很重要的⼀步啊):
sudo ldconfig
【如果报不是符号链接,就将每个转成硬链接如sudo ln -sf /sbin/ldconfig.real: /usr/local/lib/libprotobuf.so.32
】 - 成功后需要使⽤命令测试:
protoc -h
或protoc --version
- protobuf的go语⾔插件安装
- 代理配置:
go env -w GOPROXY=https://goproxy.cn
(不配置会出现“connect: connection refused”) - 安装:
go install github.com/golang/protobuf/protoc-gen-go@latest
- 进入GOPATH下的bin目录
justso@justso:/mnt/hgfs/goPath/bin$
,将protoc-gen-go可执⾏⽂件,拷贝到/bin⽬录下:sudo cp protoc-gen-go /bin/
三、protobuf应用
1- 使用protobuf开发过程
2 - 编译protobuf
- .proto文件编译:
protoc --proto_path=IMPORT_PATH --go_out=DST_DIR path/to/file.proto
- –proto_path:指定了 .proto ⽂件导包时的路径,可以有多个,如果忽略则默认当前⽬录
- –go_out:指定了⽣成的go语⾔代码⽂件放⼊的⽂件夹
- 允许使⽤
protoc --go_out=./ *.proto
的⽅式⼀次性编译多个 .proto ⽂件 - 编译时,protobuf 编译器会把 .proto ⽂件编译成 .pd.go ⽂件
- Person.proto:注意
option go_package = "./";
,一定要加上这行,否则报错protoc-gen-go: unable to determine Go import path for “Person.proto”
syntax = "proto3";
package pb;
option go_package = "./";
message Person {
string name = 1;
int32 age = 2;
repeated string emails = 3;
repeated PhoneNumber phones = 4;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
3 - 测试
package main
import (
"fmt"
"google.golang.org/protobuf/proto"
pb "myDemo/protoBufDemo/pb"
)
func main() {
person := &pb.Person{
Name: "Wuyazi",
Age: 16,
Emails: []string{"danbing.at@gmail.com", "danbing_at@163.com", "liudanbing@itcast.cn"},
Phones: []*pb.PhoneNumber{
&pb.PhoneNumber{
Number: "13131333113",
Type: pb.PhoneType_MOBILE,
},
&pb.PhoneNumber{
Number: "11111111111",
Type: pb.PhoneType_HOME,
},
&pb.PhoneNumber{
Number: "222222222222",
Type: pb.PhoneType_WORK,
},
},
}
data, err := proto.Marshal(person)
if err != nil {
fmt.Println("marshal err: ", err)
}
newPerson := &pb.Person{}
err = proto.Unmarshal(data, newPerson)
if err != nil {
fmt.Println("unmarshal err: ", err)
}
fmt.Println("源数据: ", person)
fmt.Println("解码之后的数据: ", newPerson)
}
- 备注:如果"github.com/golang/protobuf/proto"的import报红
- Linux下使用方法如下:
- mkdir -p /root/gopath/src/google.golang.org
- cd //root/gopath/src/google.golang.org
- git clone https://e.coding.net/robinqiwei/googleprotobuf.git
- Windows下使用方法:
- 找到你的GOPATH/src目录,新建google.golang.org文件夹
- 在google.golang.org目录下执行
- git clone https://e.coding.net/robinqiwei/googleprotobuf.git protobuf
- 更简单的方法:就是使用VM的共享目录的功能,然后使用Windows的方法,golang可以成功执行后,Linux就可以执行了