php 使用 protobuf
编辑于 2022-04-19 14:55:12 阅读 1952
协议缓冲区(Protocol Buffers)是一种语言中立、平台中立的可扩展机制,用于序列化结构化数据。
安装
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.20.0/protobuf-php-3.20.0.tar.gz
tar -zxvf protobuf-php-3.20.0.tar.gz
cd protobuf-3.20.0
./configure --prefix=/usr/local/protobuf
make
make install
#软链
ln -s /usr/local/protobuf/bin/protoc /usr/bin/
php extension and library
extension 和 library 二选一
extension
cd ext/google/protobuf
pear package
sudo pecl install protobuf-{VERSION}.tgz
library
composer require google/protobuf
测试
vi person.proto
syntax="proto3";
package test;
message Person{
string name=1;//姓名
int32 age=2;//年龄
bool sex=3;//性别
}
#生成php代码
protoc --php_out=./ person.proto
#即
GPBMetadata/Person.php
Test/Person.php
# 使用
<?php
require_once __DIR__ . '/../vendor/autoload.php';
include 'GPBMetadata/Person.php';
include 'Test/Person.php';
//序列化
//$person = new Test\Person();
//$person->setName("lailaiji");
//$person->setAge("28");
//$person->setSex(true);
//$data = $person->serializeToString();
//file_put_contents('data.bin', $data);
//反序列化
$bindata = file_get_contents('./data.bin');
$person = new Test\Person();
$person->mergeFromString($bindata);
echo $person->getName();
逆向推理
假如我们拿到一个序列化后的数据,比如:data.bin
,怎么解析呢?
首先,使用命令decode一下
root@php-fpm:/var/www/php-demo/protobuf# protoc --decode_raw < data.bin
1: "\345\274\240\344\270\211"
2: 28
3: 1
4 {
1: "\345\214\227\344\272\254"
2: "\346\234\235\351\230\263"
3: 100000
}
我们大致知道哪个字段是字符串,哪个字段是数字,然后可以写出这样的proto文件
syntax="proto3";
package test;
message Item {
string field1=1;
int32 field2=2;
int32 field3=3;
Obj field4=4;
message Obj {
string field1=1;
string field2=2;
int32 field3=3;
}
}
命名为person.proto
接着,生成php代码
protoc --php_out=./ person.proto
接着,写反序列化代码
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
include 'GPBMetadata/Person.php';
include 'Test/Item.php';
include 'Test/Item/Obj.php';
//反序列化
$bindata = file_get_contents('./data.bin');
$person = new Test\Item();
$person->mergeFromString($bindata);
echo $person->serializeToJsonString();
最后,运行代码,输出
{"field1":"张三","field2":28,"field3":1,"field4":{"field1":"北京","field2":"朝阳","field3":100000}}
这就清晰多了,字段的值也看到了,再次修改person.proto
文件,把字段改成更有意义的
常用命令
protoc --php_out=./ person.proto
protoc --decode_raw < data.bin
应用场景
- 直播平台的弹幕
- 用到json的地方都可以用,比如接口的响应数据
参考
https://www.jianshu.com/p/ce098058edf0