基於http協議使用protobuf進行先後端交互

protobuf介紹

因爲網上關於protobuf的交互的資料比較零散,因此本身整理了一下關於protobuf先後端交互的資料,以做參考。

Google Protocol Buffers 簡稱 Protobuf,它提供了一種靈活、高效、自動序列化結構數據的機制,能夠聯想 XML,可是比 XML 更小、更快、更簡單。僅須要自定義一次你所需的數據格式,而後用戶就可使用 Protobuf 編譯器自動生成各類語言的源碼,方便的讀寫用戶自定義的格式化的數據。與語言無關,與平臺無關,還能夠在不破壞原數據格式的基礎上,依據老的數據格式,更新現有的數據格式。前端

先後端交互方式

先後端都是以二進制形式進行交互信息。先後端定義proto後綴的文件,以此文件來當文檔來進行溝通。java

protobuf文件形式

如下爲protobuf文件的demo,test.proto,文件的結構確實簡單明瞭。node

enum FOO {
  BAR = 1;
}

message Test {
  required float num  = 1;
  required string payload = 2;
  optional string payloads = 3;
}

message AnotherOne {
  repeated FOO list = 1;
}
複製代碼

先後端進行protobuf的環境安裝

後端以node爲例子: 安裝bufferhelper以及protocol-buffers進行解析protobuf文件ios

npm install bufferhelper
npm install protocol-buffers
複製代碼

前端須要安裝解析protobuf的環境。 mac使用brew安裝protobuf環境。此操做須要先安裝Homebrew環境。具體的Homebrew的安裝自行搜索。 windows的前端環境安裝有點不同,自行搜索。npm

brew install protobuf
複製代碼

測試前端proto環境是否是安裝好了,若是有版本就是安裝好了。json

protoc --version
複製代碼

在進行先後端交互以前,前端須要進行編譯proto文件。 test.proto爲前端以及後端相同的proto文件。先編譯爲js文件再執行。首先進入node項目的proto的目錄下面,執行下面的命令以後會生成test_pb.js文件。最後js只須要解析這個文件便可。前端也須要執行這樣的操做,由於我這邊是先後端分離的。是兩個項目,因此兩個項目都須要編譯。axios

protoc --js_out=import_style=commonjs,binary:. test.proto
複製代碼

後端給前端傳數據

後端賦值proto文件的內容並傳給前端。 後端傳protobuf二進制給前端,要先轉化爲json才能夠給前端。否則的話前端會轉化成亂碼的。前端須要請求此路由。windows

app.get('/proto/get', function (req, res) {
  let protobuf = require('protocol-buffers')
  let messages=protobuf(fs.readFileSync('./proto/test.proto')
  let buf = messages.Test.encode({
    num: 42,
    payload: 'hello world node js and javahhh呵呵呵',
    payloads: ''
  })
  console.log(buf) // 打印出來的是二進制流
  res.send(JSON.stringify(buf)); //須要進行json化而後給前端。否則的話瀏覽器會自動解析成文字的
})
複製代碼

前端須要進行接受二進制流 先引入proto.js文件以及protobufjs插件後端

import awesome from '../../proto/test_pb.js'
複製代碼

前端用axios請求/proto/get的路由,在回調函數裏的res.data爲後端的返回值。進行如下操做。打印出來的message3也是解析好的文件。瀏覽器

axios({
      method:'get',
      url: '/proto/get',
      headers: { 'contentType':'application/x-protobuf'} }).then(res => {
      let message3 = awesome.Test.deserializeBinary(res.data.data)
      let nums = message3.getNum()
      console.log(nums) // nums=42。解析出來就是後端傳過來的42
      let pm = awesome.Test.deserializeBinary(res.data.data)
      let protoBuf = pm.toObject()
      console.log('protoBuf: ', protoBuf) // 打印出來是一個對象
    }).catch((error) => {
      console.log(error)
    })

複製代碼

前端給後端傳數據

前端須要進行proto文件的賦值以及轉換爲二進制給後端 引入須要依賴的文件。

import awesome from '../../proto/test_pb.js'
  import protobuf from 'protobufjs'
複製代碼
let message = new awesome.Test() // 調用Person對象  實例化
    // 賦值
    message.setNum(23)
    message.setPayload('asd')
    // 序列化
    let bytes = message.serializeBinary() //  字節流
    let blob = new Blob([bytes], {type: 'buffer'});
    axios({
      method:'post',
      url: '/proto/send',
      data: blob,
      headers: {
        'Content-Type': 'application/octet-stream' // 這裏根據後臺要求進行設置的,若是沒有要求應該是 application/octet-stream (二進制流)
      }
    }).then(res => {
      console.log(res)
    }).catch((error) => {
      console.log(error)
    })
複製代碼

後端須要接受文件 引入文件

let BufferHelper = require('bufferhelper');
複製代碼

接收字節流的代碼

app.post('/proto/send', function (req, res) {
  let bufferHelper = new BufferHelper();
  req.on("data", function (chunk) {
    bufferHelper.concat(chunk);
  });
  req.on('end', function () {
    let protobuf = require('protocol-buffers')
    let buffer = bufferHelper.toBuffer();
    console.log(buffer) // 這裏已經就是二進制文件了
    let message3 = awesome.Test.deserializeBinary(buffer)
    console.log(message3.getNum()) // 打印的就是前端傳的23
    let pm = awesome.Test.deserializeBinary(buffer)
    let protoBuf = pm.toObject()
    console.log(protoBuf) // 打印的是{ num: 23, payload: 'asd', payloads: 'asds' }
    console.log(protoBuf.num) // 打印23
  });
})
複製代碼

以上就是關於protobuf的先後交互。若有錯誤,請指出。

相關文章
相關標籤/搜索