Flutter上線項(xiàng)目實(shí)戰(zhàn)——即時(shí)通訊Protobuf

一、應(yīng)用背景:

Protobuf是google 的一種數(shù)據(jù)交換的格式,它獨(dú)立于語言,獨(dú)立于平臺。

優(yōu)點(diǎn):

  • json優(yōu)點(diǎn)就是較XML格式更加小巧,傳輸效率較xml提高了很多,可讀性還不錯(cuò)。
  • xml優(yōu)點(diǎn)就是可讀性強(qiáng),解析方便。
  • protobuf優(yōu)點(diǎn)就是傳輸效率快(據(jù)說在數(shù)據(jù)量大的時(shí)候,傳輸效率比xml和json快10-20倍),序列化后體積相比Json和XML很小,支持跨平臺多語言,消息格式升級和兼容性還不錯(cuò),序列化反序列化速度很快。

缺點(diǎn):

  • json缺點(diǎn)就是傳輸效率也不是特別高(比xml快,但比protobuf要慢很多)。
  • xml缺點(diǎn)就是效率不高,資源消耗過大。
  • protobuf缺點(diǎn)就是使用不太方便。

在一個(gè)需要大量的數(shù)據(jù)傳輸?shù)膱鼍爸校绻麛?shù)據(jù)量很大,那么選擇protobuf可以明顯的減少數(shù)據(jù)量,減少網(wǎng)絡(luò)IO,從而減少網(wǎng)絡(luò)傳輸所消耗的時(shí)間。考慮到作為一個(gè)主打社交的產(chǎn)品,消息數(shù)據(jù)量會非常大,同時(shí)為了節(jié)約流量,所以采用protobuf是一個(gè)不錯(cuò)的選擇。

二、使用

1.引入protobuf庫

pubspec.yaml

...

protobuf: 1.0.1

2.編寫proto文件

socket.message.proto

syntax = "proto3";
package socket;

// 發(fā)送聊天信息
message Message {
  string eventId = 1;
  string from = 2;
  string to = 3;
  string createAt = 4;
  string type = 5;
  string body = 6;
}

// 收到聊天消息
message AckMessage {
  string eventId = 1;
}

3.生成proto相關(guān)Model

Terminal

protoc --dart_out=. socket.message.proto

4.編碼、發(fā)消息

a.準(zhǔn)備protobuf對象

Message message = Message();
message.eventId = '####';
message.type = 'text';
message.body = 'hello world';

b.ProtobufUtil編碼

const MESSAGE_HEADER_LEN = 2;
/// 數(shù)據(jù)編碼
static List<int> encode(int type, var content) {
    ByteData data = ByteData(MESSAGE_HEADER_LEN);
    data.setUint16(0, type, Endian.little);
    List<int> msg = data.buffer.asUint8List() + content.writeToBuffer().buffer.asUint8List();
    return msg;
}

c.發(fā)消息

/// 發(fā)送
sendSocket(int type, var content) async {
    IOWebSocketChannel channel = await SocketService.getInstance().getChannel();
    if (channel == null) return;
    List<int> msg = ProtobufUtil.encode(type, content);
    channel.sink.add(msg);
}

sendSocket(11, message)

5.收消息、解碼

a.解碼

  /// 數(shù)據(jù)解碼
  static DecodedMsg decode(data) {
    Int8List int8Data = Int8List.fromList(data);
    Int8List contentTypeInt8Data = int8Data.sublist(0, MESSAGE_HEADER_LEN);
    Int8List contentInt8Data = int8Data.sublist(MESSAGE_HEADER_LEN, int8Data.length);
    int contentType = contentTypeInt8Data.elementAt(0);


    GeneratedMessage content;
    switch (contentType) {
      case 10:
        content = AckMessage.fromBuffer(contentInt8Data);
        break;
      case 11:
        content = Message.fromBuffer(contentInt8Data);
        break;
    }

    DecodedMsg decodedMsg;
    if (contentType != null && content != null) {
      decodedMsg = DecodedMsg(
        contentType: contentType,
        content: content,
      );
    }
    return decodedMsg;
  }
  

b.收消息

  channel.stream.listen((data) {
    DecodedMsg msg = ProtobufUtil.decode(data);
  }


完結(jié),撒花??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容