IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Flutter 中 Dio 和 Socket 发送 和 接收 Protobuf 数据 -> 正文阅读

[移动开发]Flutter 中 Dio 和 Socket 发送 和 接收 Protobuf 数据

Dio 使用 proto

  1. 在pubspec.yaml 安装 dio
dio: ^4.0.6
  1. 编译protobuf文件

    proto转为dart

  2. 发送和接收proto, 可以根据个人的需求,进行封装


// 定义一个方法
static ProPost (Function callBack) async {
	var proto = SearchUserInfoRequest.create();  //  SearchUserInfoRequest 为proto中的message
	var userinfo = HttpUserInfo.create();
	var url = ""; // Ip:Prot
	userinfo.userGuid = "22222";
	userinfo.userName = "jack";
	Uint8List buf = userinfo.writeToBuffer();
	Options option = Options(
		headers: {
			Headers.contentTypeHeader: "application/x-www-form-urlencoded",
			Headers.accepHeader: "*"
		},
		method:"POST",
		contentType:"application/x-www-form-urlencoded",
		responseType: ResponseType.bytes,
	);
	var dio  = Dio();
	try {
		final response = await dio.request(url,options:option,data:buf);
		// 获取到的数据,通过指定的message 解析
		DevicesAndGroupsMessage tlcs = DevicesAndGroupsMessage.fromBuffer(response.data);
	} on DioError catch (e) {
		var ei = e.response?.data;
		print(ei.runtimeType); // Uin8List
		// 个人特殊需求
		TlcsErrorRequest tlcs = TlcsErrorRequest.fromBuffer(ei);
		return tlcs;
	}
	return;
	callBack(tlcs);
}
  1. 修改dio插件
    进入dio.dart 文件中找到
late Transformer transformer;

然后进入transformer.dart文件,修改transformRequest这个方法,
我们会发现在transformRequest中 数据必须是 String ,我们需要数据为Uint8Listdio仅仅只是data.toString(),显然这样是不支持发送Uint8List数据的,因此我们修改一下

修改前:

// 26行
Future<String> transformRequest(RequestOptions options);

// 72行
  @override
  Future<String> transformRequest(RequestOptions options) async {
    var data = options.data ?? '';
    if (data is! String) {
      if (Transformer.isJsonMimeType(options.contentType)) {
        return json.encode(options.data);
      } else if (data is Map) {
        options.contentType =
            options.contentType ?? Headers.formUrlEncodedContentType;
        return Transformer.urlEncodeMap(data);
      }
    }
    return data.toString();
  }

修改后


// 26行
Future<String> transformRequest(RequestOptions options);

// 72行
  @override
  Future<String> transformRequest(RequestOptions options) async {
    var data = options.data ?? '';
    if (data is! String) {
	      if (Transformer.isJsonMimeType(options.contentType)) {
	        return json.encode(options.data);
	      } else if (data is Map) {
	        options.contentType =
	            options.contentType ?? Headers.formUrlEncodedContentType;
	        return Transformer.urlEncodeMap(data);
	      } else if(data is Uint8List) {
	        /*
	        return data;
	        github上,我见也有人直接 return data;直接返回Uint8List类型
	        我自己试了一下,在未知的位置又报错了,因此可以使用 String.fromCharCodes()
	        */ 
			return String.fromCharCodes(data);
		  }
    }
    return data.toString();
  }

Socket 使用 proto

  1. 在pubspec.yaml 安装 web_socket_channel
web_socket_channel: ^1.1.0
  1. 编译protobuf文件

    proto转为dart

  2. 发送和接收proto, 可以根据个人的需求,进行封装

// 简单一个类
class ProtoMsg {
	static late Socket channel;
	// 创建连接
	static createWs(Ip,Prot) async {
		await Socket.connect(Ip,Prot,timeout: const Duration(seconds:10)).then((value) {
			channel = value;
			channel.asBroadcastStream();
		}).catchError((onError) {
		    // 连接失败,重连
			createWs(Ip,Prot);
		});
	}
	// 关闭连接
	static void dispos() {
		channel.close();
	}
	// 发送数据
	static writeData(buffer) async {
	    /*
	    	* 头标记 code(4个字节) : 10000
	    	* 数据大小 (4个字节) : leng
	    	* 保留大小 (4个字节) : 保留
	    	* 数据内容 leng个字节
		*/
	    /*
		    // 特殊操作,有关于dart字节的操作
			var leng = buffer.length; // 获取到proto数据的长度
			ByteData bdata = ByteData(12 + leng); // 前12个字节预留位置,后面的字节为proto的数据
			var id = await ByteData.view(bdate.buffer, 0 , 4); //0位开始,4个字节,用于填写code值
			id.setUint32(0,10000); // 设置 code值
			var length = await ByteData.view(bdata.buffer,4,4); // 4位开始,4个字节,设置proto数据的长度
			length.setUint32(0,leng); // 设置 proto的长度
			var body = await ByteData.view(bdata.buffer,12,buffer.length); // 12位开始,proto数据字节长度,设置proto的数据
			for(var i = 0;i<leng;i++) {
				body.setUint8(i,buffer[i]); // 设置proto数据
			}
			var buf = Uint8List.view(body.buffer);
			channel.add(buf);
		 */
		channel.add(buffer);
	}
	static onReceiver(event) {
		print(event);
		ProtoMsg.parseData(event);
	}
	static parseData(Uint8List event) async {
		/*
	    	* 头标记 code(4个字节) : 10000
	    	* 数据大小 (4个字节) : leng
	    	* 保留大小 (4个字节) : 保留
	    	* 数据内容 leng个字节
		*/
	    /*
		    // 特殊操作,有关于dart字节的操作
		    Uint8List id = event.sublist(0,4); // 截取前4个字节
			var data = event.sublist(12);
			var number = await ByteData.view(id.buffer).getInt32(0); // 获取到code值
			if(number == 500) {
				TlcsErrorRequest tlcs = TlcsErrorRequest.fromBuffer(data); // 反序列化数据
			}
		*/
		
		TlcsErrorRequest tlcs = TlcsErrorRequest.fromBuffer(event);
	}
  }
	// 使用方式
	ProtoMsg.createWs("","");
	var userinfo = HttpUserInfo.create();
	userinfo.userGuid = "22222";
	userinfo.userName = "jack";
	Uint8List buf = userinfo.writeToBuffer();// 序列号数据
	ProtoMsg.channel.listen(onReceiver);  // 接收到数据
	ProtoMsg.writeData(buf); // 发送数据

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:57:45  更:2022-07-03 11:00:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 3:07:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码