FLUTTER· flutter下使用protobuf和socket与服务器通信实例

简要

这篇文章主要讲解在flutter中使用socket与服务器进行基于protobuf协议进行通信的基本方法包含protobuf的基本使用,数据编码的方法,以及socket建立,通信的过程
阅读时可能需要你事先对flutter,protobuf有基本了解

flutter的基本操作可以在flutter中文网中找到

在flutter中protobuf的导入

  1. 在pubspec中添加 然后更新
dependencies:
  flutter:
    sdk: flutter
    // 引入protobuf
  protobuf: ^0.13.4
  1. 使用pb的dart插件生成你的模型文件

过程简单请百度一下

举例flutter中socket的基本使用

  1. 引入头文件 创建地址和端口
import 'dart:io';
//地址
const String adress = '你的服务器地址';
//端口
const int port = 你的服务器端口;
  1. 设置一个管理类
class Client {


//socket实例
  Socket _socket;
//数据接收组
  var _recList;

//单例方法
  factory Client() =>_getInstance();

  static Client get instance => _getInstance();

  static Client _instance;

  Client._internal() {

    // 初始化
  }
  static Client _getInstance() {

    if (_instance == null) {

      _instance = new Client._internal();

    }

    return _instance;
  }
}
  1. 初始化socket实例传输并接受数据
  Future<Null> startClient() async {

//初始化接收组
    _recList = new List<int>();
//建立链接
    _socket=await Socket.connect(adress, port);
//添加数据监听
    _socket.transform(base64.encoder).listen((data){
//接受数据并处理
      List dataList = base64Decode(data);
  //接收后处理 详情可见下文
      readData(dataList);
    });
  }

在protobuf中,与服务器交换的数据是模型的纯data,而在dart中data类型用List类型表示,因此在本例中使用base64对收回数据进行编码后解码为List以供pb解析

  1. 发送数据
 void sendMsg(List msg){

    _socket.add(msg);

  }

flutter中protobuf的基本使用

构建消息体

  1. 引入pb文件以及数据处理文件
import 'package:prgramFile/all.pbserver.dart';
import 'package:fixnum/fixnum.dart';

本例中因使用int64类型数据因此需引入 fixnum: ^0.10.9

  1. 创建一个消息
const int CLIENT_TAG_BEGIN = 10000;
//心跳包
Msg heartBeatrMsg(){

  HeartbeatReq req = HeartbeatReq.create();
  
  req.count = CLIENT_TAG_BEGIN;
  
  Head head = new Head();
  
  head.msgid = MsgID.heart_beat_id;
  
  Msg msg =new Msg();
  
  msg.head = head;
  
  msg.heartbeatQ = req;
  
  return msg;
}

关于pb消息构建的内容可以百度相关教程

消息的编码和解码

使用 Msg.fromBuffer() 方法从二进制数据获取模型。

该方法为类方法

使用 msg.writeToBuffer()方法将实例转换为二进制数据

该方法为实例方法

使用Socket与服务器进行pb协议数据传输的实例

本例中服务器对数据协议的规则为消息的前8位是描述一个模型数据长度的字符串,不足8位的补"0",根据后台对数据规则定义不同因此仅供数据处理参考

  1. 对发出的消息添加描述长度的索引头
    由于实际服务器获取的是消息的前8个字节数据按照字符串处理,对应的纯data类型为 Uint8List(8)
    将每一位按照ascII表数字对应即可
  //添加索引头
  List appendHeaderWithMsg(Msg bodyMsg){
    //获取消息长度
    String bodyLength = bodyMsg.writeToBuffer().length.toString();
    //补0位数
    int supplementCount = 8 - bodyMsg.writeToBuffer().length.toString().length;
    //新索引头
    Uint8List headerList = Uint8List(8);
    //填入索引信息
    for(int i = 0;i < supplementCount; i++){
      //补0
      headerList[i] = 48;
    }
    for(int i = supplementCount;i < 8; i++){
      //有效信息
      headerList[i] = 48 + num.tryParse(bodyLength.substring(i - supplementCount,i - supplementCount + 1));
    }
   //序列化
    List resultList = headerList + bodyMsg.writeToBuffer();

    return resultList;
  }
  1. 发送消息
void sendMsg(List msg){

   _socket.add(msg);

 }
  1. 接收以及处理
  void readData(List dataList){
//接收并暂存
  _recList = _recList + dataList;
    //当接收到的数据长度大于8读取消息头
    while(_recList.length > 8 ){

        int headerLength = 8;
       //读取消息体长度
        int msgLength = int.parse(utf8.decode(_recList.sublist(0,8)));

        int sourceLength = _recList.length;
        //当收到的消息超过消息头描述的消息体长度时取出消息体并解码
        if(_recList.length >= headerLength + msgLength){

          Msg msg =  Msg.fromBuffer(_recList.sublist(headerLength,headerLength + msgLength));
          //读取后删除已读取的消息
          _recList = _recList.sublist(headerLength + msgLength,sourceLength);
        }

    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值