湖光倒影 发表于 2024-7-15 18:37

web中基于Protobuf的简明通信实例

Google Protocol Buffer的呈现已经有些年头了,目前Google官方提供了现今「java、php、js、go...」常用编程语言的API类库。本文通过web端js与处事器端php的交互,基于protobuf来实现简单的通信。



流程图

编译器protoc的安装

https://github.com/google/protobuf/releases按照开发环境,下载相应的版本;
1.当地mac端,可直接通过brew 进行安装:$ brew install protobuf2.处事器端(linux环境):wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-php-3.5.1.tar.gz
tar -xzf protobuf-php-3.5.1.tar.gz
cd protobuf-php-3.5.1/
./configure
make && make install查抄是否安装成功:
$ protoc --version编写test.proto文件

syntax = ”proto3”;
package lm;
message test
{
int32 id = 1;
string str = 2;
int32 opt = 3;
}编译test.proto文件

1.生成js包,有两种方式:Closure imports和 CommonJS imports
参考google/protobuf 本文使用CommonJS imports方式
$ protoc --js_out=import_style=commonjs,binary:./ test.proto命令运行后,当前文件夹会生成 test_pb.js 文件,但是此文件直接在网页中引用会报错,需要做如下工作「提示:当地环境需配置npm、browserify」:
$ npm install google-protobuf// test_pb.js中需要引入google-protobuf.js
$ browserify test_pb.js -o build.js // 生成 打包之后的文件生成的 build.js 文件,就可以在网页中直接使用了。
2.生成php包$ protoc --php_out=./ test.proto即可生成相应的php类库 test.php 文件
对于php的协议,官方也提供了两种运行方式,纯php编写的类库包和c扩展实现,两者运行方式无差异,任选一种都行。
参考 google/protobufsudo composer require google/protobuf //通过composer方式,安装纯php编写的类库包或
sudo pecl install protobuf //通过pecl,安装c扩展实现通信实现

前端 code<!DOCTYPE html>
<html lang=”en”>
<head>
    <meta charset=”utf-8”>
    <meta name=”viewport” content=”width=device-width, initial-scale=1, shrink-to-fit=no”>
    <title>App</title>
    <script src=”https://cdn.bootcss.com/jquery/2.2.2/jquery.min.js”></script>
</head>
<body>
    <div id=”root”></div>
    <!-- 引入生成的js包文件 -->
    <script src=”build.js”></script>
    <script>
      var test = new proto.lm.test();
      test.setId(10);
      test.setStr(&#39;hello world&#39;);
      test.setOpt(200);
      var str = test.serializeBinary();

      var formData = new FormData();
      formData.append(&#39;data&#39;, str);

      $.ajax({
                url: &#39;http://localhost/index.php&#39;,
                type: &#39;post&#39;,
                processData: false,
                contentType: false,
                data: formData,
                success: function (result) {
                  var res = result.split(”,”);
                  var x = new Uint8Array(res);
                  var data = proto.lm.test.deserializeBinary(x);
                  console.log(data.getStr());
                },
                error: function (jqXHR, textStatus, errorThrown) {
                  console.log(textStatus + ”---” + errorThrown);
                }
            });
    </script>
</body>
</html>后端 codeinclude &#39;vendor/autoload.php&#39;; //如果使用c扩展的话,这个可省略了
include &#39;Lm/test.php&#39;; //引入生成包文件
include &#39;GPBMetadata/Test.php&#39;;

$data = $_POST; //获取请求
$from = new \Lm\test();
$req = explode(”,”, $data[&#39;data&#39;]);
$str = &#39;&#39;;
foreach($req as $value){
    $str .= pack(”C”, intval($value));
}
$from->mergeFromString($str);
$str = $from->getStr();

$to = new \Lm\test();
$to->setId(10);
$to->setStr(&#39;server message, client:&#39;.$str);
$to->setOpt(2900);

$data = $to->serializeToString();
$data = unpack(”C*”, $data);
echo implode(”,”, $data);
exit;番外网上讨论的此外 一种实现方式,如下:
//php端
$to = new \Lm\test();
$to->setStr(&#39;test string&#39;);
$data = $to->serializeToString();
$data = base64_encode($data); //通过base64编码
exit($data);

//js端
$.post(”http://localhost/index.php”, function(result){
    var data = proto.lm.test.deserializeBinary(result);//客户端可直接解析base64编码
    console.log(data.getStr());
});常见问题

1. ubuntu下编译protobuf 呈现protoc: error while loading shared libraries: libprotoc.so.8: cannot open shared,解决方式参考:2.PHP中pack、unpack的详细用法,参考:
页: [1]
查看完整版本: web中基于Protobuf的简明通信实例