赞
踩
协议:必选项,默认是 ws 协议,如果需要安全加密则使用 wss。
地址:必选项,可以是 ip 或域名,当然建议使用域名。
端口:可选项,在不指定的情况下,ws 的默认端口为 80,wss 的默认端口为 443。
资源:可选性,一般是跟在域名后某资源路径,我们基本不需要它。
0 CONNECTING 尚未建立连接。
1 OPEN WebSocket连接已建立,可以进行通信。
2 CLOSING 连接正在进行关闭握手,或者该close()方法已被调用。
3 CLOSED 连接已关闭。
如果要发送的数据是二进制,我们可以通过 websocket 对象的 binaryType 属性来指定二进制的类型,binaryType 只可以被设置为“blob”或“arraybuffer”,默认为“blob”。如果我们要传输的是文件这样较为固定的、用于写入到磁盘的数据,使用 blob。而你希望传输的对象在内存中进行处理则使用较为灵活的 arraybuffer。如果要从其他非 blob 对象和数据构造一个 blob,需要使用 blob 的构造函数。
检测 websocket 对象的 readyState 是否为 OPEN,是才进行 send。
检测 websocket 对象的 bufferedAmount 是否为0,是才进行 send(为了避免消息堆积,该属性表示调用 send 后堆积在 websocket 缓冲区的还未真正发送出去的数据长度)。
onopen:连接成功后调用。
onmessage:有消息过来时调用:传入的对象有 data 属性,可能是字符串、blob 或 arraybuffer。
onerror:出现网络错误时调用:传入的对象有 data 属性,通常是错误描述的字符串。
onclose:连接关闭时调用:传入的对象有 code、reason、wasClean 等属性。
注意:当网络出错时,会先调用 onerror 再调用 onclose,无论何种原因的连接关闭,onclose 都会被调用。
默认的 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个,比如一个主连接负责处理大厅等业务消息,一个战斗连接直接连战斗服务器,或者连接聊天服务器。
- 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接口
- 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); // 关闭接口
- }
- // 网络提示接口
- export interface INetworkTips {
- connectTips(isShow: boolean): void;
- reconnectTips(isShow: boolean): void;
- requestTips(isShow: boolean): void;
- }
连接的建立与鉴权(是否鉴权、如何鉴权由用户的回调决定)
断线重连后的数据重发处理
心跳机制确保连接有效(心跳包间隔由配置,心跳包的内容由ProtocolHelper定义)
连接的关闭
支持断线重传,超时重传
支持唯一发送(避免同一时间重复发送)
支持持续监听
支持request-respone模式
可自定义网络延迟、短线重连等状态的表现
NetNode 自身的状态变量,如 ISocket 对象、当前状态、连接参数等等。
各种回调,包括连接、断开连接、协议处理、网络提示等回调。
各种定时器,如心跳、重连相关的定时器。
请求列表与监听列表,都是用于接收到的消息处理。
init 方法用于初始化 NetNode,主要是指定 Socket 与协议等处理对象。
connect 方法用于连接服务器。
initSocket 方法用于绑定 Socket 的回调到 NetNode 中。
updateNetTips 方法用于刷新网络提示。
这里确保没有重复之所以使用的是遍历 _requests,是因为我们不会积压大量的请求到 _requests中,超时或异常重发也不会导致 _requests 的积压,因为重发的逻辑是由 NetNode 控制的,而且在网络断开的情况下,我们理应屏蔽用户发起请求,此时一般会有一个全屏遮罩——网络出现波动之类的提示。
该例子连接的是 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();
- }
- }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。