cocos creator 教程:框架 - 网络

【muzzik 教程】:框架 - 网络

实现功能

  • 基础功能(连接、发送、接收、重连、心跳、编解码)

  • 多网络连接

  • 消息请求(等待返回)

  • 发送潮(批量发送)

  • 服务端消息模拟

模块结构

平台适配

// ...

protobufjs 使用

安装

  1. npm i protobufjs
  2. npm i --save-dev protobufjs-cli

    这是 pbjs/pbts 的命令行工具,旧版的 protobufjs pbjs/pbts 是直接在包内的,最新的分开了

导入

  • 默认:import protobufjs from "protobufjs";
  • 指定版本:import protobufjs from "protobufjs/minimal.js";

pbjs/pbts 生成

pbjs

注意:如果你们项目内 package.json 存在属性 "type": "module" 则使用 es6 的生成类型,否则使用 commonjs 的生成类型

使用 commonjs 的生成类型

npx pbjs -t static-module -w commonjs -l eslint-disable --keep-case -o ./test.js ./*.proto
后处理
  • -------------------------------分割-----------------------------

    var $protobuf = require("protobufjs/minimal");
    

    替换为

    var $protobuf = require("protobufjs/minimal.js");
    
  • -------------------------------分割-----------------------------

    var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
    

    替换为

    var $root = {};
    

使用 es6 的生成类型

npx pbjs -t static-module -w es6 -l eslint-disable --es6 --keep-case -o ./test.js ./*.proto
后处理
  • -------------------------------分割-----------------------------

    import * as $protobuf from "protobufjs/minimal";
    

    替换为

    import $protobuf from "protobufjs/minimal.js";
    
  • -------------------------------分割-----------------------------

    const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
    

    替换为

    const $root = {};
    

pbts

由于 creator 模块规范限制导入 js 必须存在扩展名(.js),所以我们导出的文件名后缀必须是 *.js.d.ts

npx pbts -m -o ./声明文件名.js.d.ts ./proto静态模块.js
后处理

可选:$protobuf 替换为 protobuf 避免 vscode 飘红


怎么添加消息号?

目前论坛里的方法都是通过 二次包装 或者 拼接消息号 实现

  • 二次包装:消息号的消息体包装消息 bytes 类型的消息体

proto 定义

message send_data {
   uint32 id = 1;
   bytes body = 2;
}

message send_data_body {
   string data = 1;
}

使用

/** 消息体字节 */
const body = test.send_data_body.encode(test.send_data_body.create({ data: "1" })).finish();
/** 消息 */
const mess = test.send_data
	.encode(
		test.send_data.create({
			id: 100,
			body: body,
		})
	)
	.finish();
  • 拼接消息号:将消息号添加到消息数据头部

使用

const buff = new ArrayBuffer(消息号占用字节 + 消息体占用字节);
const data2 = new Uint8Array(buff);
const data3 = new DataView(buff);

// 设置消息号
data3.setUint16(0, 消息号);
// 设置消息体
data2.set(消息体, 2);
有没有更高效更方便的方式呢?当然是有的,我在自己的框架中实现了这种方式,也就是使用 默认值

proto 定义

message test {
    uint32 __id = 1 [default = 100];
    string data = 2;
}

使用

// 编码
const body = test.test.create({ data: "1" });

body["__id"] = body["__id"];
const mess = test.test.encode(body).finish();
// 解码

/** 消息体 */
const data_uint8_as = new Uint8Array(data_);
/** 消息号 */
const id_n = protobufjs.Reader.create(data_uint8_as).skipType(0).uint32();
/** 消息 */
const mess = this._mess_map.get(id_n);

return mess.decode(data_uint8_as)

使用默认值的好处

  • 发送接口不需传递消息号,只需消息体就可知消息号
  • 更省传输字节
  • 更好的性能

参考

性能比较

  • 1w 次
    image

  • 10w 次
    image

proto 定义

package test;
>syntax = "proto3";

message test {
   uint32 __id = 1 [default = 100];
   string data = 2;
}

message send_data {
	uint32 id = 1;
   bytes body = 2;
}

message send_data_body {
   string data = 1;
}

测试代码

// 二次包装
{
	this._log.time_start("二次包装");
	let temp: any;

	for (let k_n = 0; k_n < for_n; ++k_n) {
		/** 消息体字节 */
		const body = test.send_data_body.encode(test.send_data_body.create({ data: "1" })).finish();

		/** 消息 */
		temp = test.send_data
			.encode(
				test.send_data.create({
					id: 100,
					body: body,
				})
			)>
			.finish();
	}
	this._log.time_end("二次包装");
}

// 拼接消息号
{
	this._log.time_start("拼接消息号");
	for (let k_n = 0; k_n < for_n; ++k_n) {
		/** 消息体字节 */
		const body = test.send_data_body.encode(test.send_data_body.create({ data: "1" })).finish();
		const buff = new ArrayBuffer(2 + body.length);
		const mess = new Uint8Array(buff);
		const data_view = new DataView(buff);

		// 设置消息号
		data_view.setUint16(0, 100);
		// 设置消息体
		mess.set(body, 2);
	}
	this._log.time_end("拼接消息号");
}

// 默认消息号(mk 框架)
{
	this._log.time_start("默认消息号");
	let temp: any;

	for (let k_n = 0; k_n < for_n; ++k_n) {
		const body = test.test.create({ data: "1" });

		// eslint-disable-next-line no-self-assign
		body["__id"] = body["__id"];
		temp = test.test.encode(body).finish();
	}
	this._log.time_end("默认消息号");
}
posted @ 2023-01-19 20:53  Muzzik  阅读(1919)  评论(0编辑  收藏  举报