大神驾到 | 腾讯光子大牛的 Cocos Creator 网络通用框架(强势围观)
项目源码
使用websocket
构造 websocket 对象
协议:必选项,默认是 ws 协议,如果需要安全加密则使用 wss。
地址:必选项,可以是 ip 或域名,当然建议使用域名。
端口:可选项,在不指定的情况下,ws 的默认端口为 80,wss 的默认端口为 443。
资源:可选性,一般是跟在域名后某资源路径,我们基本不需要它。
websocket 的状态
0 CONNECTING 尚未建立连接。
1 OPEN WebSocket连接已建立,可以进行通信。
2 CLOSING 连接正在进行关闭握手,或者该close()方法已被调用。
3 CLOSED 连接已关闭。
websocket 的 API
如果要发送的数据是二进制,我们可以通过 websocket 对象的 binaryType 属性来指定二进制的类型,binaryType 只可以被设置为“blob”或“arraybuffer”,默认为“blob”。如果我们要传输的是文件这样较为固定的、用于写入到磁盘的数据,使用 blob。而你希望传输的对象在内存中进行处理则使用较为灵活的 arraybuffer。如果要从其他非 blob 对象和数据构造一个 blob,需要使用 blob 的构造函数。
检测 websocket 对象的 readyState 是否为 OPEN,是才进行 send。
检测 websocket 对象的 bufferedAmount 是否为0,是才进行 send(为了避免消息堆积,该属性表示调用 send 后堆积在 websocket 缓冲区的还未真正发送出去的数据长度)。
websocket 的回调
onopen:连接成功后调用。
onmessage:有消息过来时调用:传入的对象有 data 属性,可能是字符串、blob 或 arraybuffer。
onerror:出现网络错误时调用:传入的对象有 data 属性,通常是错误描述的字符串。
onclose:连接关闭时调用:传入的对象有 code、reason、wasClean 等属性。
注意:当网络出错时,会先调用 onerror 再调用 onclose,无论何种原因的连接关闭,onclose 都会被调用。
Echo 实例
默认的 url 前缀是wss,由于 wss 抽风,使用 ws 才可以连接上,如果 ws 也抽风,可以试试连这个地址ws://121.40.165.18:8800,这是国内的一个免费测试 websocket 的网址。
https://www.w3.org/TR/websockets/9
https://developer.mozilla.org/en-US/docs/Web/API/Blob6
http://www.websocket.org/echo.html17
http://www.websocket-test.com/2
设计框架
用户协议差异,游戏可能传输 json、protobuf、flatbuffer 或者自定义的二进制协议。
底层协议差异,我们可能使用 websocket、或者微信小游戏的 wx.websocket、甚至在原生平台我们希望使用 tcp/udp/kcp 等协议。
登陆认证流程,在使用长连接之前我们理应进行登陆认证,而不同游戏登陆认证的方式不同。
网络异常处理,比如超时时间是多久,超时后的表现是怎样的,请求时是否应该屏蔽 UI 等待服务器响应,网络断开后表现如何,自动重连还是由玩家点击重连按钮进行重连,重连之后是否重发断网期间的消息?等等这些。
多连接的处理,某些游戏可能需要支持多个不同的连接,一般不会超过2个,比如一个主连接负责处理大厅等业务消息,一个战斗连接直接连战斗服务器,或者连接聊天服务器。
ProtocolHelper
export type NetData = (string | ArrayBufferLike | Blob | ArrayBufferView); // 协议辅助接口
export interface IProtocolHelper { getHeadlen(): number; // 返回包头长度 getHearbeat(): NetData; // 返回一个心跳包 getPackageLen(msg: NetData): number; // 返回整个包的长度 checkPackage(msg: NetData): boolean; // 检查包数据是否合法 getPackageId(msg: NetData): number; // 返回包的id或协议类型
}
Socket
// Socket接口
export interface ISocket { onConnected: (event) => void; // 连接回调 onMessage: (msg: NetData) => void; // 消息回调 onError: (event) => void; // 错误回调 onClosed: (event) => void; // 关闭回调 connect(ip: string, port: number); // 连接接口 send(buffer: NetData); // 数据发送接口 close(code?: number, reason?: string); // 关闭接口
}
NetworkTips
// 网络提示接口
export interface INetworkTips { connectTips(isShow: boolean): void; reconnectTips(isShow: boolean): void; requestTips(isShow: boolean): void;
}
NetNode
连接的建立与鉴权(是否鉴权、如何鉴权由用户的回调决定)
断线重连后的数据重发处理
心跳机制确保连接有效(心跳包间隔由配置,心跳包的内容由ProtocolHelper定义)
连接的关闭
支持断线重传,超时重传
支持唯一发送(避免同一时间重复发送)
支持持续监听
支持request-respone模式
可自定义网络延迟、短线重连等状态的表现
NetNode 自身的状态变量,如 ISocket 对象、当前状态、连接参数等等。
各种回调,包括连接、断开连接、协议处理、网络提示等回调。
各种定时器,如心跳、重连相关的定时器。
请求列表与监听列表,都是用于接收到的消息处理。
init 方法用于初始化 NetNode,主要是指定 Socket 与协议等处理对象。
connect 方法用于连接服务器。
initSocket 方法用于绑定 Socket 的回调到 NetNode 中。
updateNetTips 方法用于刷新网络提示。
onConnected 方法在网络连接成功后调用,自动进入鉴权流程(如果设置了_connectedCallback),在鉴权完成后需要调用 onChecked 方法使 NetNode 进入可通讯的状态,在未鉴权的情况,我们不应该发送任何业务请求,但登录验证这类请求应该发送给服务器,这类请求可以通过带force参数强制发送给服务器。
这里确保没有重复之所以使用的是遍历 _requests,是因为我们不会积压大量的请求到 _requests中,超时或异常重发也不会导致 _requests 的积压,因为重发的逻辑是由 NetNode 控制的,而且在网络断开的情况下,我们理应屏蔽用户发起请求,此时一般会有一个全屏遮罩——网络出现波动之类的提示。
NetManager
测试例子
该例子连接的是 websocket 官方的 echo.websocket.org 地址,这个服务器会将我们发送给它的所有消息都原样返回给我们。
// 不关键的代码省略 @ccclass
export default class NetExample extends cc.Component { @property(cc.Label) textLabel: cc.Label = null; @property(cc.Label) urlLabel: cc.Label = null; @property(cc.RichText) msgLabel: cc.RichText = null; private lineCount: number = 0; onLoad() { let Node = new NetNode(); Node.init(new WebSock(), new DefStringProtocol()); Node.setResponeHandler(0, (cmd: number, data: NetData) => { if (this.lineCount > 5) { let idx = this.msgLabel.string.search("\n"); this.msgLabel.string = this.msgLabel.string.substr(idx + 1); } this.msgLabel.string += `${data}\n`; ++this.lineCount; }); NetManager.getInstance().setNetNode(Node); } onConnectClick() { NetManager.getInstance().connect({ url: this.urlLabel.string }); } onSendClick() { NetManager.getInstance().send(this.textLabel.string); } onDisconnectClick() { NetManager.getInstance().close(); }
}
小结
大神驾到 | 腾讯光子大牛的 Cocos Creator 网络通用框架(强势围观)相关推荐
- 大神驾到 | 麒麟子带你初识Cocos Shader
一.什么是Cocos Shader 可能有朋友会感到奇怪,百度上搜不到Cocos Shader. 那就对了,因为Cocos Shader 是 Cocos Creator 3D Shader的简称. 是 ...
- android 双电池,国外大神拆解腾讯ROG游戏手机5,双电池、中置主板结构、散热用料优秀...
国外大神拆解腾讯ROG游戏手机5,双电池.中置主板结构.散热用料优秀 2021-03-22 16:33:50 14点赞 23收藏 28评论 上周,我们报道了暴力测试大神JerryRigEverythi ...
- 传智播客上海校区“大神季”腾讯课堂各学科公开课直播地址!
传智播客上海校区"大神季"腾讯课堂各学科公开课直播地址! 同学们,送福利来了! 是不是很好奇其他学科的同学都在学什么? 人工智能与Python到底是什么? JavaEE班级为什么总 ...
- mesh 协调器 路由器_请TI技术支持和大神指点下,关于zigbee组建mesh路由网络的问题,谢谢!...
1,问题描述: 我搭建了一个Mesh路由网络,网络中包含设备:1个协调器,20几个路由器节点,没有终端节点. 由于在Mesh网络中,如果协调器掉电,路由器会重新维护该原来的网络,协调器上电后网络的PA ...
- 厉害了,不能错过,大神关于TCP/IP 协议的理解分享(网络协议篇一)
本篇文章篇幅比较长,先来个思维导图预览一下. 本篇文章篇幅比较长,先来个思维导图预览一下. 一张图带你看完本篇文章 一.概述 1.计算机网络体系结构分层 计算机网络体系结构分层 2.TCP/IP 通信 ...
- 如何才能学好zbrush,成为3D建模大神,腾讯角色设计大佬给出的秘典
在我们开始用ZBrush建模作品之前,你首先要知道,选择一个能提升我们技能的新项目非常重要:比如建模.拓扑结构.纹理等等.在这个项目中,因为我想熟悉衣服和配饰的制作过程,所以我选择了一个含有这许多元素 ...
- 大神驾到|「罗斯基」教你怎么做出超休闲游戏爆款
11月13日,由罗斯基联合量江湖.Topon共同举办的"下一个休闲游戏爆款在哪里"主题沙龙活动在深圳举办.活动邀请了多家知名休闲游戏厂商以及头部休闲游戏平台的负责人,演讲内容涵盖休 ...
- 大神驾到 | 游戏UI赏析之—全面战争:三国
先点上方的"游戏UI分享"再点右上角"..."最后设为星标 看「游戏UI分享」「博物标本篇」 今天有幸邀请到[游戏UI分享]公众号作者「落笔不悔」又名「潦草线条 ...
- WD计算机网络,大神为你解决Win10系统不能在计算机-网络中访问WDMyCloud的图文技巧...
大家应该都知道我们在使用电脑的时候,会发现Win10系统不能在计算机-网络中访问WDMyCloud的问题,根据小编的了解并不是每个人都会处理Win10系统不能在计算机-网络中访问WDMyCloud的问 ...
最新文章
- angular五大服务顺序_建议收藏 | 一篇文章告诉你工种的进场顺序
- Android开机自启动 .
- Java connot reduce_Java8: Reduce方法
- filewriter判断是否关闭_各种仪表故障判断,看完你也可以成为仪表维修专家
- 女子将车垂直开上标志杆,警方回应...
- 技术面试别扯智力题!
- Docker入门安装教程
- Python判断字符串是否为数字(数字、小数、负数、负小数、0)
- asp.net5开发中DNX SDK版本的影响
- prometheus监控mysql指标_使用Prometheus监控MySQL状态
- M1 Repast Simphony打不开 无反应问题解决
- html双人可悔棋五子棋源码,MATLAB实现五子棋游戏(双人对战、可悔棋).pdf
- Asterisk增加g729编码支持
- MYSQL 人民币大写金额转小写
- 自走棋手游服务器稳定,2020最火的自走棋手游
- Redis中key-value对value的数据类型
- 解决from Crypto.Cipher import AES报错
- 用 Python 制作商品历史价格查询
- hive大数据量实现分页查询,java结合mybatis及多数据源(hive、MySQL)
- 大学英语(第三册)复习(原文及全文翻译)——Unit 7 - The Shelter(防空洞)