找回密码
 立即注册
查看: 133|回复: 0

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

[复制链接]
发表于 2024-7-15 18:37 | 显示全部楼层 |阅读模式
Google Protocol Buffer的呈现已经有些年头了,目前Google官方提供了现今「java、php、js、go...」常用编程语言的API类库。本文通过web端js与处事器端php的交互,基于protobuf来实现简单的通信。



流程图

编译器protoc的安装
https://github.com/google/protobuf/releases
按照开发环境,下载相应的版本;
1.当地mac端,可直接通过brew 进行安装:
  1. $ brew install protobuf
复制代码
2.处事器端(linux环境):
  1. wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-php-3.5.1.tar.gz
  2. tar -xzf protobuf-php-3.5.1.tar.gz
  3. cd protobuf-php-3.5.1/
  4. ./configure
  5. make && make install
复制代码
查抄是否安装成功:
  1. $ protoc --version
复制代码
编写test.proto文件
  1. syntax = ”proto3”;
  2. package lm;
  3. message test
  4. {
  5.   int32 id = 1;
  6.   string str = 2;
  7.   int32 opt = 3;
  8. }
复制代码
编译test.proto文件
1.生成js包,有两种方式:Closure imports和 CommonJS imports
参考google/protobuf
本文使用CommonJS imports方式
  1. $ protoc --js_out=import_style=commonjs,binary:./ test.proto
复制代码
命令运行后,当前文件夹会生成 test_pb.js 文件,但是此文件直接在网页中引用会报错,需要做如下工作「提示:当地环境需配置npm、browserify」:
  1. $ npm install google-protobuf  // test_pb.js中需要引入google-protobuf.js
  2. $ browserify test_pb.js -o build.js // 生成 打包之后的文件
复制代码
生成的 build.js 文件,就可以在网页中直接使用了。
2.生成php包
  1. $ protoc --php_out=./ test.proto
复制代码
即可生成相应的php类库 test.php 文件
对于php的协议,官方也提供了两种运行方式,纯php编写的类库包和c扩展实现,两者运行方式无差异,任选一种都行。
参考 google/protobuf
  1. sudo composer require google/protobuf //通过composer方式,安装纯php编写的类库包
复制代码
  1. sudo pecl install protobuf //通过pecl,安装c扩展实现
复制代码
通信实现
前端 code
  1. <!DOCTYPE html>
  2. <html lang=”en”>
  3.   <head>
  4.     <meta charset=”utf-8”>
  5.     <meta name=”viewport” content=”width=device-width, initial-scale=1, shrink-to-fit=no”>
  6.     <title>App</title>
  7.     <script src=”https://cdn.bootcss.com/jquery/2.2.2/jquery.min.js”></script>
  8.   </head>
  9.   <body>
  10.     <div id=”root”></div>
  11.     <!-- 引入生成的js包文件 -->
  12.     <script src=”build.js”></script>
  13.     <script>
  14.         var test = new proto.lm.test();
  15.         test.setId(10);
  16.         test.setStr(&#39;hello world&#39;);
  17.         test.setOpt(200);
  18.         var str = test.serializeBinary();
  19.         var formData = new FormData();
  20.         formData.append(&#39;data&#39;, str);
  21.         $.ajax({
  22.                 url: &#39;http://localhost/index.php&#39;,
  23.                 type: &#39;post&#39;,
  24.                 processData: false,
  25.                 contentType: false,
  26.                 data: formData,
  27.                 success: function (result) {
  28.                     var res = result.split(”,”);
  29.                     var x = new Uint8Array(res);
  30.                     var data = proto.lm.test.deserializeBinary(x);
  31.                     console.log(data.getStr());
  32.                 },
  33.                 error: function (jqXHR, textStatus, errorThrown) {
  34.                     console.log(textStatus + ”---” + errorThrown);
  35.                 }
  36.             });
  37.     </script>
  38.   </body>
  39. </html>
复制代码
后端 code
  1. include &#39;vendor/autoload.php&#39;; //如果使用c扩展的话,这个可省略了
  2. include &#39;Lm/test.php&#39;; //引入生成包文件
  3. include &#39;GPBMetadata/Test.php&#39;;
  4. $data = $_POST; //获取请求
  5. $from = new \Lm\test();
  6. $req = explode(”,”, $data[&#39;data&#39;]);
  7. $str = &#39;&#39;;
  8. foreach($req as $value){
  9.     $str .= pack(”C”, intval($value));
  10. }
  11. $from->mergeFromString($str);
  12. $str = $from->getStr();
  13. $to = new \Lm\test();
  14. $to->setId(10);
  15. $to->setStr(&#39;server message, client:&#39;.$str);
  16. $to->setOpt(2900);
  17. $data = $to->serializeToString();
  18. $data = unpack(”C*”, $data);
  19. echo implode(”,”, $data);
  20. exit;
复制代码
番外
网上讨论的此外 一种实现方式,如下:
  1. //php端
  2. $to = new \Lm\test();
  3. $to->setStr(&#39;test string&#39;);
  4. $data = $to->serializeToString();
  5. $data = base64_encode($data); //通过base64编码
  6. exit($data);
  7. //js端
  8. $.post(”http://localhost/index.php”, function(result){
  9.     var data = proto.lm.test.deserializeBinary(result);//客户端可直接解析base64编码
  10.     console.log(data.getStr());
  11. });
复制代码
常见问题

1. ubuntu下编译protobuf 呈现  protoc: error while loading shared libraries: libprotoc.so.8: cannot open shared,解决方式参考:
2.PHP中pack、unpack的详细用法,参考:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-8 11:02 , Processed in 0.098518 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表