找回密码
 立即注册
查看: 267|回复: 4

Flutter上线项目实战——即时通讯Protobuf

[复制链接]
发表于 2022-8-2 10:11 | 显示全部楼层 |阅读模式
一、应用背景:

Protobuf是google 的一种数据交换的格式,它独立于语言,独立于平台。
优点:

  • json优点就是较XML格式更加小巧,传输效率较xml提高了很多,可读性还不错。
  • xml优点就是可读性强,解析方便。
  • protobuf优点就是传输效率快(据说在数据量大的时候,传输效率比xml和json快10-20倍),序列化后体积相比Json和XML很小,支持跨平台多语言,消息格式升级和兼容性还不错,序列化反序列化速度很快。
缺点:

  • json缺点就是传输效率也不是特别高(比xml快,但比protobuf要慢很多)。
  • xml缺点就是效率不高,资源消耗过大。
  • protobuf缺点就是使用不太方便。
在一个需要大量的数据传输的场景中,如果数据量很大,那么选择protobuf可以明显的减少数据量,减少网络IO,从而减少网络传输所消耗的时间。考虑到作为一个主打社交的产品,消息数据量会非常大,同时为了节约流量,所以采用protobuf是一个不错的选择。
二、使用

1.引入protobuf库

pubspec.yaml
...

protobuf: 1.0.12.编写proto文件

socket.message.proto
syntax = "proto3";
package socket;

// 发送聊天信息
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相关Model

Terminal
protoc --dart_out=. socket.message.proto4.编码、发消息

a.准备protobuf对象
Message message = Message();
message.eventId = '####';
message.type = 'text';
message.body = 'hello world';
b.ProtobufUtil编码
const MESSAGE_HEADER_LEN = 2;
/// 数据编码
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.发消息
/// 发送
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.解码
/// 数据解码
  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);
  }<hr/>完结,撒花
发表于 2022-8-2 10:19 | 显示全部楼层
5月25日为啥还不支持空安全呢? 建议支持空安全再发一篇
发表于 2022-8-2 10:22 | 显示全部楼层
protobuf库吗?然而我并不是protobuf库的作者
发表于 2022-8-2 10:31 | 显示全部楼层
它已经支持了,我的意思是你的flutter版本太旧了,出一篇2.x的教程
发表于 2022-8-2 10:36 | 显示全部楼层
拆包粘包问题有解决方案吗?楼主
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-5-1 06:56 , Processed in 0.142048 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

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