一篇文章带你了解 Flutter中WebSocket的使用

1,074 阅读4分钟

json 模型

{
    "event": "message",
    "data": {
        "type": "text",
        "content": "",
        "from": ""
    }
}
event`类型:`message/name/name_ack/broadcast/error/keepalive

Flutter 客户端

  • 使用web_socket_channel

    Flutter中用于websocket 访问的库

  • 为 websocket 添加心跳机制

  • 使用 protobuf 改造案例

    全称是Google Protocol Buffer,是一种高效轻便的结构化数据存储方式,可用于(数据)通信协议、数据存储等。它与语言无关,平台无关,且高效性能好。

    img

Protobuf 语法简介

Protobuf 使用.proto文件来定义消息,一个简单示例如下

// 语法版本
syntax = "proto3";
​
message SearchRequest {
  string query = 1;
  int32 page = 2;
  int32 result = 3;
}

整体看起来和Dart中的类声明相似,message后面指定的名称,会映射成Dart的类名。消息定义中的每个字段都有一个唯一的数字 ,这是字段编号,这些字段编号用于以消息二进制格式标识字段,一旦消息类型被使用,就不应该更改这些字段。

消息嵌套

syntax = "proto3";
​
message SearchRequest {
  string query = 1;
  int32 page = 2;
​
  // 声明Result类型消息
  message Result {
    string url = 1;
    string title = 2;
  }
​
  // 在SearchRequest中定义一个Result字段
  Result result = 3;
}

这些消息中还能定义枚举。枚举的第一个常量编号映射到零,意即必须有一个字段编号为0的值

syntax = "proto3";
​
message SearchRequest {
  string query = 1;
  int32 page = 2;
  int32 result = 3;
  // 使用snippets修改,声明列表,此处为字符串列表
  repeated string snippets = 3;
​
  // 声明一个枚举类型
  enum Corpus {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
  }
​
  // 在SearchRequest中定义一个枚举字段
  Corpus corpus = 4;
}

在Dart 中的使用

  1. 下载protobuf 工具

    工具链接

  2. 安装dart语言的protoc插件

    pub global activate protoc_plugin
    

    安装插件后,需要将该插件路径配置到PATH环境变量中,Windows下是%APPDATA%\Pub\Cache\bin,Mac 或 Linux系统下是$HOME/.pub-cache/bin

  3. .proto文件编译成dart文件

    protoc --dart_out=. test.proto
    

    将生成的带pb的dart文件拷贝到项目中

  4. 项目中引入protobuf 依赖

     dependencies:
       protobuf: ^1.0.1
    

附录:字段类型对应表

.protoNotesJavaPython[2]GoDart
doubledoublefloatfloat64double
floatfloatfloatfloat32double
int32使用可变长度编码。编码负数效率低,如果您的字段可能具有负值,请改用sint32。intintint32int
int64使用可变长度编码。负数编码效率低下,如果您的字段可能具有负值,请改用sint64。longint/long[3]int64Int64
uint32使用可变长度编码。int[1]int/long[3]uint32int
uint64使用可变长度编码。long[1]int/long[3]uint64Int64
sint32使用可变长度编码。有符号的int值。这些比普通的int32更有效地编码负数。intintint32int
sint64使用可变长度编码。有符号的int值。这些比普通的int64更有效地编码负数。longint/long[3]int64Int64
fixed32始终为四个字节。如果值通常大于228,则比uint32更有效。int[1]int/long[3]uint32int
fixed64始终为八个字节。如果值通常大于256,则比uint64更有效。long[1]int/long[3]uint64Int64
sfixed32始终为四个字节。intintint32int
sfixed64始终为八个字节。longint/long[3]int64Int64
boolbooleanboolboolbool
string字符串必须始终包含UTF-8编码或7位ASCII文本,并且不能超过232。Stringstr/unicode[4]stringString
bytes可以包含不超过232个任意字节序列。ByteStringstr[]byteList

[1]在Java中,无符号的32位和64位整数使用带符号的对等体表示,最高位仅存储在符号位中。

[2]在所有情况下,对字段设置值都会进行类型检查以确保其有效。

[3]64位或无符号32位整数在解码时始终表示为long,但是如果在设置字段时给出了int,则可以为int。 在所有情况下,该值都必须适合设置时表示的类型。 参见[2]。

[4]Python字符串在解码时表示为unicode,但如果给出了ASCII字符串,则可以为str(此字符串可能会发生变化)。