这篇文章主要讲解在flutter中使用socket与服务器进行基于protobuf协议进行通信的基本方法包含protobuf的基本使用,数据编码的方法,以及socket建立,通信的过程
阅读时可能需要你事先对flutter,protobuf有基本了解
flutter的基本操作可以在flutter中文网中找到
dependencies:
flutter:
sdk: flutter
// 引入protobuf
protobuf: ^0.13.4
过程简单请百度一下
import 'dart:io';
//地址
const String adress = '你的服务器地址';
//端口
const int port = 你的服务器端口;
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;
}
}
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解析
void sendMsg(List msg){
_socket.add(msg);
}
import 'package:prgramFile/all.pbserver.dart';
import 'package:fixnum/fixnum.dart';
本例中因使用int64类型数据因此需引入 fixnum: ^0.10.9
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()方法将实例转换为二进制数据
该方法为实例方法
本例中服务器对数据协议的规则为消息的前8位是描述一个模型数据长度的字符串,不足8位的补"0",根据后台对数据规则定义不同因此仅供数据处理参考
//添加索引头
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;
}
void sendMsg(List msg){
_socket.add(msg);
}
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);
}
}