使用cocoscreator + node.js + websocket实现简单的聊天服务

转载:https://www.cnblogs.com/skyxu123/p/9810741.html
我觉得很有学习意义~~
若有不妥。请联系我删除!
先上个效果图:

使用cocoscreator 1.9.1 + node.js + websocket实现,没有使用socket.io, 全部自己封装,长连接进行封装后可以和短连接使用方法一样,使用简单,方便以后开发网络游戏。

1、客户端:

主要就是聊天内容的显示,自动换行和背景扩展,代码大概如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
cc.Class({
extends: cc.Component,

properties: {
    msgLabel: cc.Label,
    uidLabel: cc.Label,
    msgLayout: cc.Layout,
    msgBg: cc.Node,
    maxLen: 500,
},

// LIFE-CYCLE CALLBACKS:

// onLoad () {},

start () {
    this.node.runAction(cc.fadeTo(0.5, 255))
},

initMsg(msg, uid){
    this.msgLabel.string = msg;
    this.uidLabel.string = uid;

    this.msgLabel.overflow = cc.Label.Overflow.NONE;
    // this.msgBg.width = this.msgLabel.node.width + 10;
    // this.msgBg.height = this.msgLabel.node.height + 10;
    // this.node.height = this.msgBg.height + 40;

    this.scheduleOnce((dt)=>{
        if ( this.msgLabel.node.width >= this.maxLen){
            this.msgLabel.overflow = cc.Label.Overflow.RESIZE_HEIGHT;
            this.msgLabel.node.width = this.maxLen;
        }

        this.msgBg.width = this.msgLabel.node.width + 10;
        this.msgBg.height = this.msgLabel.node.height + 10;
        this.node.height = this.msgBg.height + 40;

    }, 0);

    this.node.opacity = 0;
}

// update (dt) {},

});
  网络部分分成了四层:

1、socket 封装基础的websocket, 这里是最底层,也是真正链接的开始

2、network 控制socket链接层,实现各回调接口

3、netproxy 封装各服务功能,把长连接变成短连接的请求方式

4、netprotocols 和服务器协商,确定每个请求的请求体格式和回复格式

各部分代码如下:

GameWebSocket.js:

复制代码
/**

  • @enum {number}
    */
    var GameWebSocketState = cc.Enum({
    CONNECTING: 1,
    OPEN: 2,
    CLOSING: 3,
    CLOSED: 4
    });

/**

  • @interface
    */
    var GameWebSocketDelegate = cc.Class({

    onSocketOpen: function () {

    },

    /**

    • 收到了消息
    • @param {string|Uint8Array} data
      */
      onSocketMessage: function (data) {

    },

    onSocketError: function () {

    },

    /**

    • 连接关闭
    • @param {string} reason
      */
      onSocketClosed: function (reason) {

    }
    });

/**

  • @interface
    */
    var GameWebSocketInterface = cc.Class({

    connect: function () {

    },

    send: function () {

    },

    close: function () {

    },

    getState: function () {

    }
    });

var GameWebSocket = cc.Class({
extends: GameWebSocketInterface,

properties: {

    /**
     * @type {String} 服务器地址
     */
    _address: null,

    /**
     * @type {GameWebSocketDelegate}
     */
    _delegate: null,

    /**
     * @type {WebSocket}
     */
    _webSocket: null,
},

/**
 * @param {string} address 服务器地址
 * @param {GameWebSocketDelegate} delegate 回调接口
 */
init: function(address, delegate){
    this._address = address;
    this._delegate = delegate;
    this._webSocket = null;
},

connect: function () {
    cc.log('connect to '+ this._address);

    var ws = this._webSocket = new WebSocket(this._address);
    ws.onopen = this._delegate.onSocketOpen.bind(this._delegate);
    ws.onmessage = function (param) {
        this._delegate.onSocketMessage(param.data);
    }.bind(this);
    ws.onerror = this._delegate.onSocketError.bind(this._delegate);
    // function({code: Number, reason: String, wasClean: Boolean})}
    ws.onclose = function (param) {
        this._delegate.onSocketClosed(param.reason);
    }.bind(this);
},

/**
 * 发送数据
 * @param {string|Uint8Array} stringOrBinary
 */
send: function (stringOrBinary) {
    this._webSocket.send(stringOrBinary);
},

close: function () {
    if (!this._webSocket) {
        return;
    }

    try {
        this._webSocket.close();
    } catch (err) {
        cc.log('error while closing webSocket', err.toString());
    }
    this._webSocket = null;
},

getState: function () {
    if (this._webSocket) {
        switch(this._webSocket.readyState){
            case WebSocket.OPEN:
                return GameWebSocketState.OPEN;
            case WebSocket.CONNECTING:
                return GameWebSocketState.CONNECTING;
            case WebSocket.CLOSING:
                return GameWebSocketState.CLOSING;
            case WebSocket.CLOSED:
                return GameWebSocketState.CLOSED;
        }
    }
    return GameWebSocketState.CLOSED;
}

});

module.exports = {
GameWebSocketState: GameWebSocketState,
GameWebSocketDelegate: GameWebSocketDelegate,
GameWebSocketInterface: GameWebSocketInterface,
GameWebSocket: GameWebSocket
};
复制代码
  GameNetwork.js

复制代码
/**

  • Created by skyxu on 2018/10/9.
    */

“use strict”;

let GameWebSocket = require("./GameWebSocket");
let GameProtocols = require("./GameProtocols");

/**

  • 服务器回复消息状态,判断回复消息的各种问题
    */
    var response_state = {
    ERROR_OK : ‘0’
    };

/**

  • 请求回调对象,收到服务器回调后的回调方法
    */
    var NetworkCallback = cc.Class({

    properties: {

     /**
      * @type {BaseRequest} request
      */
     request: null,
    
     /**
      * 请求回调对方法
      */
     callback: null
    

    },

    /**

    • @param {BaseRequest} request
    • @param {function(BaseResponse): boolean} callback
      */
      init: function (request, callback) {
      this.request = request;
      this.callback = callback;
      }
      });

let GameNetwork = cc.Class({
extends: GameWebSocket.GameWebSocketDelegate,

ctor: function() {
    this._socket = null;

    this._delegate = null;

    /**
     * 每次发送请求,都需要有一个唯一的编号
     * @type {number}
     * @private
     */
    this._requestSequenceId = 0;

    /**
     * 接受服务器主动下发的response回调
     * key 表示BaseResponse.act
     * @type {Object.<string, function(object.<string, *>)>}
     */
    this.pushResponseCallback = {};

    /**
     * 根据seq保存Request和其callback,以便在收到服务器的响应后回调
     * @type {Object.<int, NetworkCallback>}
     * @private
     */
    this._networkCallbacks = {};
},

setDelegate: function (delegate) {
    this._delegate = delegate;
},

/**
 * 注册服务器主动推送的response 回调
 */
registerPushResponseCallback : function(act, callback){
    this.pushResponseCallback[act] = callback;
},

/**
 * 判断socket已连接成功,可以通信
 * @returns {boolean}
 */
isSocketOpened: function(){
    return (this._socket && this._socket.getState() == GameWebSocket.GameWebSocketState.OPEN);
},

isSocketClosed: function () {
    return this._socket == null;
},

/**
 * 启动连接
 */
connect: function (url) {
    cc.log("webSocketUrls=" + url);
    this._requestSequenceId = 0;
    this._socket = new GameWebSocket.GameWebSocket();
    this._socket.init(url, this);
    this._socket.connect();
},

closeConnect: function () {
    if(this._socket){
        this._socket.close();
    }
},

onSocketOpen: function () {
    cc.log('Socket:onOpen');
    if(this._delegate && this._delegate.onNetworkOpen){
        this._delegate.onNetworkOpen();
    }
},

onSocketError: function () {
    cc.log('Socket:onError');
},

onSocketClosed: function (reason) {
    cc.log('Socket:onClose', reason);
    if (this._socket) {
        this._socket.close();
    }
    this._socket = null;

    if(this._delegate && this._delegate.onNetworkClose){
        this._delegate.onNetworkClose();
    }
},

onSocketMessage: function (msg) {
    this._onResponse(msg);
},

_onResponse: function(responseData){
    cc.log('response->resp:', responseData);
    var responseJson = JSON.parse(responseData);
    var responseClass = GameProtocols.response_classes[responseJson.act];
    /**
     * @type {object.<BaseResponse>}
     */
    var response = new responseClass();
    response.loadData(responseJson.data);
    response.act = responseJson.act;
    response.seq = responseJson.seq;
    response.err = responseJson.err;
    response.ts = responseJson.ts;

    // 如果指定了回调函数,先回调
    var ignoreError = false;
    if(response.seq != -1){
        // 处理服务器推送消息
        var pushCallback = this.pushResponseCallback[response.act];
        if(pushCallback){
            pushCallback(response);
        }

        // request回调
        var callbackObj = this._networkCallbacks[response.seq];
        if(callbackObj){
            ignoreError = callbackObj.callback(response);
            // try {
            //     ignoreError = callbackObj.callback(response);
            // } catch (err) {
            //     cc.log(err + " error in response callback of " + response.act);
            // } finally {
            //     delete this._networkCallbacks[response.seq];
            // }
        }
    }

    //有错,且不忽略,则统一处理错误
    if(response.err && response.err != response_state.ERROR_OK && !ignoreError){
        if (response.is_async) {  // 异步请求,如果出错了,应该需要重新登录
            // todo 重新登录?或者重新同步数据?
        } else {  // 同步请求,如果出错了,需要显示错误信息
            // todo 显示错误
            var msg = responseJson.msg;
            cc.log('server err ' + msg);
        }
    }
},

/**
 * 向服务器发送请求。
 *
 * 如果提供了callback,在收到response后会被回调。如果response是一个错误(status!=ERR_OK),则需要决定由谁来负责处理错误。
 * 如果callback中已经对错误进行了处理,应该返回true,这样会忽略该错误。否则应该返回false,则负责处理该错误。
 *
 * 特别注意:如果这是一个异步(is_async)请求,且出错,一般来讲应该重新登录/同步。但是如果callback返回了true,不会进行
 * 任何处理,也就是不会重新登录/同步。请小心确定返回值。
 *
 * @param {object.<BaseRequest>}
 * @param {function(BaseResponse): boolean=} opt_callback 回调函数。出错的情况下,如果返回true,则不会再次处理错误。
 */
sendRequest: function (request, opt_callback) {
    // 每个请求的seq应该唯一,且递增
    request.seq = ++this._requestSequenceId;

    //生成NetworkCallback对象,绑定请求seq和回调方法
    if(opt_callback){
        this._networkCallbacks[request.seq] = new NetworkCallback();
        this._networkCallbacks[request.seq].init(request, opt_callback);
    }
    this._sendSocketRequest(false, request);
},

/**
 * sendRequest的不发送data字段
 */
sendRequestNoData: function (request, opt_callback) {
    // 每个请求的seq应该唯一,且递增
    request.seq = ++this._requestSequenceId;

    //生成NetworkCallback对象,绑定请求seq和回调方法
    if(opt_callback){
        this._networkCallbacks[request.seq] = new NetworkCallback();
        this._networkCallbacks[request.seq].init(request, opt_callback);
    }
    this._sendSocketRequest(true, request);
},

/**
 * @param {Boolean} isNoData
 * @param {object.<BaseRequest>} req
 */
_sendSocketRequest: function (isNoData, req) {
    cc.assert(this._socket);

    if (this.isSocketOpened()){
        //通过json的方法生成请求字符串
        var msg = null;
        if(isNoData){
            msg = JSON.stringify({seq:req.seq, act:req.act});
        }else{
            msg = JSON.stringify({seq:req.seq, act:req.act, data:req});
        }
        cc.log("WebSocketDelegate::send->" + msg);
        this._socket.send(msg);
    } else{
        // todo
    }
}

});

module.exports = GameNetwork;
复制代码
  GameProtocols.js

复制代码
/**

  • Created by skyxu on 2018/10/9.
    */

“use strict”;

/**

  • 消息基类对象,请求消息BaseRequest, 回调消息BaseResponse都继承BaseProtocol
    /
    let BaseProtocol = cc.Class({
    ctor: function () {
    /
    *
    * 请求动作类型
    */
    this.act = ‘’;

     /**
      * 每个请求的sequence_id应该唯一
      */
     this.seq = 0;
    
     /**
      * 错误代码,0为正常
      */
     this.err = 0;
    
     /**
      * 是否需要等待服务器回调
      */
     this.is_async = false;
    

    }
    });

/**

  • 请求消息基类,客户端的请求都继承这个类
    */
    let BaseRequest = cc.Class({
    extends: BaseProtocol
    });

/**

  • 服务器返回的消息对应的对象,包含返回数据,一般和BaseRequest成对使用

  • @class BaseResponse

  • @extends BaseProtocol
    */
    let BaseResponse = cc.Class({
    extends: BaseProtocol,

    /**

    • 读取返回数据,设置BaseResponse对象
      */
      loadData: function (data) {
      var key;
      for (key in data) {
      if(!this.hasOwnProperty(key)){
      continue;
      }

       if(data[key] !== undefined && data[key] !== null){
           this[key] = data[key];
       }
      

      }
      }
      });

let HeartRequest = cc.Class({
extends: BaseRequest,
ctor(){
this.act = ‘heart’;
this.t = -1; // 发送时间
}
});

let HeartResponse = cc.Class({
extends: BaseResponse,

ctor(){
    this.act = 'heart';
    this.t = -1;
}

});

let ChatRequest = cc.Class({
extends: BaseRequest,
ctor(){
this.act = ‘chat’;
this.msg = ‘’;
this.uid = ‘’;
}
});

let ChatResponse = cc.Class({
extends: BaseResponse,
ctor(){
this.act = ‘chat’;
this.msg = ‘’;
this.uid = ‘’;
}
});

let LoginRequest = cc.Class({
extends: BaseRequest,

ctor: function () {
    this.act = 'login';

    /**
     * facebook用户的accessToken,或游客的UUID
     */
    this.token = '';

    /**
     * token来源,默认0:游客,1:facebook
     */
    this.origin = 0;

    /**
     * 平台: 必须为以下几种之一:android/ios/winphone/pc
     */
    this.os = '';

    /**
     * 平台系统版本
     */
    this.osVersion = '';

    /**
     * 设备产品型号, 示例 iPhone8,2, SM-G 9280
     */
    this.deviceModel = '';

    /**
     * 渠道ID
     */
    this.channelId = 0;

    /**
     * Ios设备广告标示符
     */
    this.idfa = '';

    /**
     * 安卓设备id
     */
    this.androidId = '';

    /**
     * Google广告平台账号,安装了google play的设备可取到
     */
    this.googleAid = '';

    /**
     * 应用版本号
     */
    this.appVersion = '';

    /**
     * 取package name或者bundle id
     */
    this.packName = '';


    /**
     * 设备语言
     * @type {string}
     */
    this.language = '';

    this.locale = "";

}

});

let LoginResponse = cc.Class({
extends: BaseResponse,

ctor: function () {
    this.act = 'login';

    /**
     * 游客第一次登录时返回的token,需要客户端保存
     */
    this.token = '';

    /**
     * 离体力下次恢复点的剩余时间秒数
     * @type {number}
     */
    this.spStepLeftTime = 0;

    /**
     * 体力恢复周期
     * @type {Number}
     */
    this.spInterval = 0;

    /**
     * 农场每天产出量,产出未解锁时为-1
     * @type {number}
     */
    this.farmDailyOut = -1;

    /**
     * 农场已产出量
     * @type {number}
     */
    this.farmCoins = 0;

    /**
     * 农场产出间隔
     * @type {number}
     */
    this.farmInterval = null;

    /**
     * 用json object表示的一个player对象,字段说明参见player json对象
     */
    this.me = {};

    /**
     * 建筑数据数组
     * @type {Array}
     */
    this.buildings = [];

    /**
     * 农民数据数组
     * @type {Array}
     */
    this.farms = [];

    /**
     * 富豪数据
     */
    this.cashking = {};

    /**
     * 行星配置
     */
    this.planetConf = {};

    /**
     * 农民配置
     */
    this.farmConfList = [];

    /**
     * 其他配置
     */
    this.settingConf = {};

    /**
     * 好友数据
     */
    this.friends = [];

    /**
     * 好友通缉的目标列表
     */
    this.helpWantList = [];

    /**
     * 邮件消息列表
     */
    this.newsList = [];

    /**
     * 复仇列表
     */
    this.revengeList = [];

    /**
     * 商品信息
     * @type {Array}
     */
    this.rechargeConfs = [];

    /**
     * 总岛数
     * @type {Number}
     */
    this.planetConfListSize = 0;

    /**
     * 他人行星信息对象,仅在转到fire断线重新登录时有效
     * @type {Object}
     */
    this.fireTarget = null;

    /**
     * 他人行星信息对象列表,仅在转到steal断线重新登录时有效
     * @type {Array}
     */
    this.stealTarget = null;
}

});

let LogoutRequest = cc.Class({
extends: BaseRequest,

ctor: function () {
    this.act = 'logout';
}

});

let LogoutResponse = cc.Class({
extends: BaseResponse,

ctor: function () {
    this.act = 'logout';
}

});

/**

  • 绑定fb账号

  • @extends BaseRequest
    */
    let BindFacebookRequest = cc.Class({
    extends: BaseRequest,

    ctor: function () {
    this.act = ‘bindFb’;

     /**
      * facebook用户的accessToken,或游客的UUID
      */
     this.token = '';
    

    }
    });
    /**

  • 绑定fb账号

  • @extends BaseResponse
    */
    let BindFacebookResponse = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = ‘bindFb’;

     /**
      * fb数据
      */
     this.me = 0;
    
     /**
      * fb好友
      */
     this.friends = 0;
    

    }
    });

let SpinRequest = cc.Class({
extends: BaseRequest,

ctor: function () {
    this.act = 'spin';

    /**
     * 倍数
     * @type {Number}
     */
    this.x = 1;
}

});

let SpinResponse = cc.Class({
extends: BaseResponse,

ctor: function () {
    this.act = 'spin';

    /**
     * 摇中的转盘ID
     */
    this.hit = 0;

    /**
     * 转到护盾,但护盾已满时,存在
     * @type {number}
     */
    this.shieldfull = 0;

    /**
     * 玩家数据对象
     */
    this.me = {};

    /**
     * 他人行星信息对象,仅在转到fire时有效
     * @type {*}
     */
    this.fireTarget = {};

    /**
     * 偷取对象数据
     */
    this.stealTarget = [];

    /**
     * 离体力下次恢复点的剩余时间秒数
     * @type {number}
     */
    this.spStepLeftTime = 0;

    /**
     * 体力恢复周期
     * @type {Number}
     */
    this.spInterval = 0;

    /**
     * 倍数
     * @type {Number}
     */
    this.x = 1;
}

});

/**

  • 获取排名

  • @extends BaseRequest
    */
    let RankRequest = cc.Class({
    extends: BaseRequest,

    ctor: function () {
    this.act = ‘rankboard’;

     /**
      * 请求动作类型{ 0全部,1本地,2好友 }
      * @type {int}
      */
     this.type = 0;
    

    }
    });
    /**

  • 获取排名

  • @extends BaseResponse
    */
    let RankResponse = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = ‘rankboard’;

     /**
      *  我的排名
      */
     this.myRank = 0;
    
     /**
      * 排名玩家数据
      */
     this.men = [];
    

    }
    });

//push------------------------------------------------------------------------------

/**

  • 推送消息 被攻击

  • @extends BaseResponse
    */
    var PushAttackedResponse = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = ‘attacked’;

     /**
      * 玩家更新数据
      */
     this.me = null;
    
     /**
      * 建筑数据
      */
     this.building = null;
    
     /**
      * 敌人
      */
     this.hatredman = null;
    
     /**
      * 消息
      */
     this.news = null;
    

    }
    });

/**

  • 推送消息 推送消息好友已赠送体力

  • @extends BaseResponse
    */
    var PushSendSpResponse = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = ‘sendSpNotify’;

     /**
      * 好友对象
      */
     this.friend = null;
    

    }
    });

/**

  • 推送消息 推送消息好友已领取赠送的体力

  • @extends BaseResponse
    */
    var PushTakeSpResponse = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = ‘takeSpNotify’;

     /**
      * 好友对象
      */
     this.friend = null;
    

    }
    });

/**

  • 推送消息 同步好友信息

  • @extends BaseResponse
    */
    var PushSyncFriendInfo = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = ‘friendInfoSync’;

     /**
      * 好友
      */
     this.friend = null;
    

    }
    });

/**

  • 推送消息 新增好友

  • @extends BaseResponse
    */
    var PushAddNewFriend = cc.Class({
    extends: BaseResponse,

    ctor: function () {

     this.act = 'newFriend';
    
     /**
      * 好友
      */
     this.friend = null;
    
     /**
      * 消息
      */
     this.news = null;
    

    }
    });

/**

  • debug回调

  • @extends BaseRequest
    */
    let DebugChangeMeRequest = cc.Class({
    extends: BaseRequest,

    ctor: function () {

     this.act = "cmdTest";                    //请求动作类型
     this.cmd = "";
     //  "player coins add 100", cmd格式:player field value 或者 player field add value
     //  Building field [add] value where playerId value type value
    

    }

});
/**

  • debug回调

  • @extends BaseResponse
    */
    let DebugChangeMeResponse = cc.Class({
    extends: BaseResponse,

    ctor: function () {
    this.act = “cmdTest”;

     /**
      * 玩家数据
      * @type {Object}
      */
     this.me = {};
    
     /**
      * 体力恢复周期
      * @type {Number}
      */
     this.spInterval = null;
    
     /**
      * 体力恢复剩余时间
      * @type {Number}
      */
     this.spStepLeftTime = null;
    
     /**
      * 存钱罐速度
      * @type {Number}
      */
     this.farmDailyOut = null;
    
     /**
      * 存钱罐可回收金币
      * @type {Number}
      */
     this.farmCoins = null;
    
     /**
      * 存钱罐回收周期
      * @type {Number}
      */
     this.farmInterval = null;
    
     /**
      * 岛屿建筑数据
      * @type {Array}
      */
     this.buildings = null;
    

    }
    });

let response_classes = {
login: LoginResponse,
logout: LogoutResponse,
spin: SpinResponse,
bindFb: BindFacebookResponse,
rankboard: RankResponse,
heart: HeartResponse,
chat: ChatResponse,

//push
attacked: PushAttackedResponse,
sendSpNotify: PushSendSpResponse,
takeSpNotify: PushTakeSpResponse,
newFriend: PushAddNewFriend,
friendInfoSync: PushSyncFriendInfo,

// debug
cmdTest: DebugChangeMeResponse,

};

module.exports = {
LoginRequest: LoginRequest,
LoginResponse: LoginResponse,
LogoutRequest: LogoutRequest,
LogoutResponse: LogoutResponse,
SpinRequest: SpinRequest,
SpinResponse: SpinResponse,
BindFacebookRequest: BindFacebookRequest,
BindFacebookResponse: BindFacebookResponse,
RankRequest: RankRequest,
RankResponse: RankResponse,
HeartRequest: HeartRequest,
HeartResponse: HeartResponse,
ChatRequest: ChatRequest,
ChatResponse: ChatResponse,

// debug
DebugChangeMeRequest: DebugChangeMeRequest,
DebugChangeMeResponse: DebugChangeMeResponse,

//push消息
PushAttackedResponse: PushAttackedResponse,
PushSendSpResponse: PushSendSpResponse,
PushTakeSpResponse: PushTakeSpResponse,
PushAddNewFriend: PushAddNewFriend,
PushSyncFriendInfo: PushSyncFriendInfo,

response_classes: response_classes

};
复制代码
  NetProxy.js

/**

  • Created by skyxu on 2018/10/9.
    */

“use strict”;

let GameNetwork = require("./GameNetwork");
let GameProtocols = require("./GameProtocols");

let GAME_SERVER_URL = ‘ws://127.0.0.1:3000’;
// GAME_SERVER_URL = ‘wss://echo.websocket.org’;

let NetProxy = cc.Class({
ctor: function () {
this.network = null;
this._cachePushCallback = [];
},

init: function () {
    this.network = new GameNetwork();
    this.network.setDelegate(this);
    this.initPushCallback();
},

connect: function () {
    this.network.connect(GAME_SERVER_URL);
},

closeConnect: function () {
    this.network.closeConnect();
},

isNetworkOpened: function () {
    return this.network.isSocketOpened();
},

isNetworkClosed: function () {
    return this.network.isSocketClosed();
},

onNetworkOpen: function () {
    Global.eventMgr.emit(Global.config.EVENT_NETWORK_OPENED);
},

onNetworkClose: function () {
    Global.eventMgr.emit(Global.config.EVENT_NETWORK_CLOSED);
},

/**
 * 注册push回调接口
 */
initPushCallback: function () {
    let self = this;
    let pushCallback = function (resp) {
        self.pushCallback(resp);
    };

    this.network.registerPushResponseCallback('chat', pushCallback);


    // let pushCallback = function(response){
    //     if(Util.DNN(farm.game) && farm.game.loginSuccess){
    //         this.dealCachePush();
    //         this.pushCallback(response);
    //     }else{
    //         this._cachePushCallback.push(response);
    //     }
    // }.bind(this);

    // this.network.registerPushResponseCallback('attacked', pushCallback);
    // this.network.registerPushResponseCallback('acceptWantHelp', pushCallback);
    // this.network.registerPushResponseCallback('sendSpNotify', pushCallback);
    // this.network.registerPushResponseCallback('takeSpNotify', pushCallback);
    // this.network.registerPushResponseCallback('wanted', pushCallback);
    // this.network.registerPushResponseCallback('incomplete', pushCallback);
    // this.network.registerPushResponseCallback('newFriend', pushCallback);
    // this.network.registerPushResponseCallback('news', pushCallback);
    // this.network.registerPushResponseCallback('hatredInfoSync', pushCallback);
    // this.network.registerPushResponseCallback('friendInfoSync', pushCallback);
},

/**
 * 处理缓存push
 */
dealCachePush: function () {
    // if(this._cachePushCallback.length > 0){
    //     for(var i = 0; i < this._cachePushCallback.length; i++){
    //         this.pushCallback(this._cachePushCallback[i]);
    //     }
    // }
    // this._cachePushCallback = [];
},

beatHeart: function (callback) {
    let req = new GameProtocols.HeartRequest();
    req.t = Date.now();
    this.network.sendRequest(req, callback);
},

chat: function (msg) {
    let req = new GameProtocols.ChatRequest();
    let uid = cc.sys.localStorage.getItem("chat_uid");
    req.uid = uid;
    req.msg = msg;
    this.network.sendRequest(req);
},

/**
 * Facebook或者游客登录接口
 * @param {Object.<LoginOriginType>} origin
 * @param token
 */
login: function (origin, token) {
    // let req = new GameProtocols.LoginRequest();
    // if(token) req.token = token;
    // req.origin = origin;
    // req.os = cc.sys.os;
    // req.osVersion = cc.sys.osVersion;
    // // req.language = cc.sys.language;//farm.FarmPlatformHelper.jsToOc(farm.FarmPlatformHelper.JSB_EVENT_JTO_GetCurrentLanguage);
    // /*
    //  req.deviceModel = '';
    //  req.channelId = 0;
    //  req.idfa = '';
    //  req.androidId = '';
    //  req.googleAid = '';
    //  req.appVersion = '';
    //  req.packName = '';
    //  */
    // let callback =  function (resp) {
    //     if(resp.err != 0){
    //         Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_LOGIN_FAILED, resp);
    //         return;
    //     }
    //     if(resp.token && resp.token.length > 0){
    //         farm.localStorage.setItem(farm.game.gmConst.GLS_KEY_GUEST_TOKEN, resp.token);
    //     }
    //     farm.localStorage.removeItem(farm.game.gmConst.GLS_KEY_IS_LOGOUT);
    //
    //     //
    //     farm.game.initConfig(resp);
    //     farm.game.initData(resp);
    //     farm.game.loginSuccess = true;
    //
    //     // js 调取其他平台的sdk,传过去玩家id
    //     farm.FarmPlatformHelper.jsToOc(farm.FarmPlatformHelper.JSB_EVENT_JTO_setSessionWithUid, farm.game.player.id.toString());
    //     //
    //
    //     //登录
    //     farm.eventManager.emit(farm.game.gmConst.SP_EVENT_LOGIN_SUCCESS);
    // };
    // this.network.sendRequest(req, callback);

},

/**
 * Facebook或者游客登出
 */
logout: function () {
    // let req = new GameProtocols.LogoutRequest();
    // this.network.sendRequest(req, function (resp) {
    //     if(resp.err != 0){
    //         cc.log("网络请求---LogoutRequest 失败");
    //         farm.eventManager.emit(farm.game.gmConst.SP_EVENT_LOGOUT_FAILED);
    //         return;
    //     }
    //     cc.log("网络请求---LogoutRequest 成功");
    //     Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_LOGOUT_SUCCESS);
    // });
},

/**
 * 绑定fb账号
 * @param {String} token
 */
bindFacebook: function (token) {
    // let req = new GameProtocols.BindFacebookRequest();
    // req.token = token;
    // let callback =  function (resp) {
    //     //绑定过得逻辑
    //     if(resp.err == farm.game.gmConst.ERROR_USER_HAS_REGISTERED){
    //         cc.log("网络请求---BindFacebookRequest 已绑定");
    //         farm.eventManager.emit(farm.game.gmConst.SP_EVENT_HAS_BIND_FACEBOOK);
    //         return;
    //     }
    //     //绑定失败
    //     if(resp.err != 0){
    //         cc.log("网络请求---BindFacebookRequest 失败");
    //         farm.eventManager.emit(farm.game.gmConst.SP_EVENT_BIND_FACEBOOK_FAILED);
    //         return;
    //     }
    //     //绑定成功
    //     cc.log("网络请求---BindFacebookRequest 成功");
    //     if(resp.me){
    //         farm.game.player.parse(resp.me);
    //     }
    //     if(resp.friends){
    //         farm.game.initFriends(resp.friends);
    //     }
    //     //绑定成功后删除本地token
    //     farm.localStorage.removeItem(farm.game.gmConst.GLS_KEY_GUEST_TOKEN);
    //     farm.eventManager.emit(farm.game.gmConst.SP_EVENT_BIND_FACEBOOK_SUCCESS);
    // };
    // this.network.sendRequest(req, callback);
},

/**
 * 启动转盘
 */
spin: function (x) {
    // let req = new GameProtocols.SpinRequest();
    // if(farm.util.isNumber(x)){
    //     req.x = x;
    // }
    // var callback =  function (resp) {
    //     if(resp.err != 0){
    //         cc.log("网络请求---spin 失败");
    //         farm.eventManager.emit(farm.game.gmConst.SP_EVENT_SPIN_FAILED, resp);
    //         return;
    //     }
    //     cc.log("网络请求---spin 成功");
    //     farm.game.player.parse(resp.me);
    //     farm.game.spTimer.updateSpTime(resp.spStepLeftTime, resp.spInterval);
    //     farm.eventManager.emit(farm.game.gmConst.SP_EVENT_SPIN_SUCCESS, resp);
    // };
    // this.network.sendRequest(req, callback);
},

/**
 * 获取排名
 * @param {Number} rankType 0全部,1本地,2好友
 */
getRank: function (rankType) {
    // let req = new GameProtocols.RankRequest();
    // req.type = rankType;
    // let callback =  function (resp) {
    //     if(resp.err != 0){
    //         cc.log("网络请求---getRank 失败");
    //         Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_GET_RANK_FAILED, resp);
    //         return;
    //     }
    //     cc.log("网络请求---getRank 成功");
    //     // todo 暂定排名类型
    //     resp._rankType = rankType;
    //     //farm.game.initLeaderBoardArray(rankType, resp.myRank, resp.men);
    //     if(rankType == 2 && resp.men){
    //         farm.game.updateFriends(resp.men);
    //         resp.men = farm.game.sortFriendsByStar();
    //     }
    //     Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_GET_RANK_SUCCESS, resp);
    // };
    // this.network.sendRequest(req, callback);
},


//push回调------------------------------------------------------------------------------

/**
 * 推送回调
 */
pushCallback: function (response) {
    switch (response.act){
        case "sendSpNotify":
        case "takeSpNotify":
        case "friendInfoSync":
            this.pushFriendSendTakeSp(response);
            break;
        case "stole":
            this.pushStole(response);
            break;
        case "attacked":
            this.pushAttacked(response);
            break;
        case "newFriend":
            this.pushAddNewFriend(response);
            break;
        case "chat":
            this.pushChat(response);
            break;
    }
},
/**
 * 好友间互赠体力推送
 * @param {PushSendSpResponse|PushTakeSpResponse} resp
 */
pushFriendSendTakeSp: function (resp) {
    // cc.log("网络请求---push--- pushFriendSendTakeSp 成功");
    // if(resp.friend) farm.game.updateFriends(resp.friend);
    // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_UPDATE_FRIEND);
},

/**
 * 被偷
 * @param {PushStolenResponse} resp
 */
pushStole: function (resp) {
    // cc.log("网络请求---push--- pushStole 成功");
    // if(resp.me) farm.game.player.parse(resp.me);
    // //if(resp.building) farm.game.buildings[resp.building.type].parse(resp.building);
    // if(resp.hatredman && !farm.game.getHelpWant(resp.hatredman.id)){
    //     farm.game.addEnemy(resp.hatredman);
    // }
    // if(resp.news){
    //     resp.news = farm.game.addNews(resp.news);
    // }
    // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_BE_STOLE_SUCCESS, resp);
},

/**
 * 被攻击
 * @param {PushAttackedResponse} resp
 */
pushAttacked: function (resp) {
    // cc.log("网络请求---push--- pushAttacked 成功");
    // if(resp.me) {
    //     farm.game.player.parse(resp.me);
    //     farm.game.dataUpdater.updateStar();
    // }
    // if(resp.building) farm.game.buildings[resp.building.type].parse(resp.building);
    // if(resp.hatredman){
    //     farm.game.addBadass(resp.hatredman);
    //     if(!farm.game.getHelpWant(resp.hatredman.id)){
    //         farm.game.addEnemy(resp.hatredman);
    //     }
    // }
    // if(resp.news){
    //     resp.news = farm.game.addNews(resp.news);
    // }
    // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_BE_ATTACK_SUCCESS, resp);
},

/**
 * 新增好友
 * @param {PushAddNewFriend} resp
 */
pushAddNewFriend: function (resp) {
    // cc.log("网络请求---push--- pushAddNewFriend 成功");
    // if(resp.friend){
    //     resp.friend = farm.game.addFriend(resp.friend);
    // }
    // if(resp.news){
    //     resp.news = farm.game.addNews(resp.news);
    // }
    // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_ADD_FRIEND_SUCCESS, resp);
},

pushChat: function (resp) {
    Global.eventMgr.emit(Global.config.EVENT_CHAT, resp);
},

/**
 * debug调试请求
 * @param {String} name
 */
debug_addCoins: function (name) {
    var req = new GameProtocols.DebugChangeMeRequest();
    if (name === "btnAddCoins") {
        req.cmd = "player coins add 100000000";
    } else if (name === "btnClearCoins") {
        req.cmd = "player coins 0";
    } else if (name === "btnAddEnergy") {
        req.cmd = "player sp add 10";
    } else if (name === "btnClearEnergy") {
        req.cmd = "player sp 0";
    } else if (name == "btnAddWp") {
        req.cmd = "player wp add 10";
    } else if (name == "btnClearWp") {
        req.cmd = "player wp 0";
    } else if (name == "btnUnwrap"){
        req.cmd = "player fbuid null";
    } else if (name == "btnWizard1"){
        req.cmd = "player wizard1 0";
    } else if (name == "btnWizard2"){
        req.cmd = "player wizard2 0";
    } else if (name == "btnClearShield"){
        req.cmd = "player shield 0";
    } else if (name == "btnSpEc"){
        req.cmd = "SpEc stepInterval 60000";
    } else if (name == "btnFarmEc"){
        req.cmd = "FarmEc stepInterval 60000";
    } else if (name == "btnSpEcBack"){
        req.cmd = "SpEc stepInterval 3600000";
    } else if (name == "btnFarmBack"){
        req.cmd = "FarmEc stepInterval 86400000";
    } else if (name == "btnUpdateBuild"){
        req.cmd = "Building lv 5";
    } else {
        req.cmd = name;
    }
    // var callback = function (resp) {
    //     if (resp.err != 0) {
    //         return;
    //     }
    //     farm.game.player.parse(resp.me);
    //     farm.game.spTimer.updateSpTime(resp.spStepLeftTime, resp.spInterval);
    //     farm.game.dataUpdater.updateCoin();
    //     farm.game.dataUpdater.updateSp();
    //     farm.game.dataUpdater.updateShield();
    //     farm.game.dataUpdater.updateStar();
    //     //
    //     if((req.cmd == "FarmEc stepInterval 60000" || req.cmd == "FarmEc stepInterval 86400000")
    //         && farm.util.isNumber(resp.farmDailyOut)
    //         && farm.util.isNumber(resp.farmCoins)){
    //         farm.game.piggyBankTimer.init(resp.farmDailyOut, resp.farmCoins, resp.farmInterval);
    //     }
    //     if(req.cmd == "SpEc stepInterval 60000" || req.cmd == "SpEc stepInterval 3600000"){
    //         farm.game.spTimer.updateSpTime(resp.spStepLeftTime, resp.spInterval);
    //     }
    //     if(resp.buildings){
    //         for(var i = 0; i < resp.buildings.length; ++i){
    //             farm.game.buildings[i].parse(resp.buildings[i]);
    //         }
    //         farm.eventManager.emit(farm.game.gmConst.SP_EVENT_UPGRADE_BUILDING_SUCCESS, resp);
    //         farm.eventManager.emit(farm.game.gmConst.SP_DEBUG_EVENT_BUILD_TO_24_SUCCESS, resp);
    //     }
    // };
    // this.network.sendRequest(req, callback);
},

});

module.exports = NetProxy;
2、服务端

使用express + express-ws组件,调用WSRouter的init初始化连接即可,

复制代码
let expressWS = require(‘express-ws’);
let work = require(’./work’);

let wsRouter = null;

function WSRouter(app, server){
this.app = app;
this.server = server;
this.clients = [];
expressWS(app, server);

this.listenClientConnection = ()=>{
    app.ws('/', (socket, req)=>{
        console.log('client connect to server successful.');
        this.clients.push(socket);
        console.log('clients: ' + this.clients.length);
        socket.on('message', (msg)=>{
            console.log('on message: ' + msg);
            work(this, socket, msg);
        });

        socket.on('close', (msg)=>{
            console.log('on close: ' + msg);
            for (let index=0; index<this.clients.length; index++){
                if (this.clients[index] == socket){
                    this.clients.splice(index,1);
                }
            }
            console.log('clients: ' + this.clients.length);
        });

        socket.on('error', (err)=>{
            console.log('on error: ' + error);
        });
    })
}

}

module.exports = {
init: function(app, server){
if (wsRouter == null){
wsRouter = new WSRouter(app, server);
}
return wsRouter;
}
}
复制代码
复制代码
module.exports = function(wsRouter, ws, msg){
let msgObj = JSON.parse(msg);
switch (msgObj.act){
case ‘heart’:{
msgObj.data.t = Date.now();
ws.send(JSON.stringify(msgObj));
break;
}
case ‘chat’: {
for (let w of wsRouter.clients){
w.send(msg);
}
break;
}

    default:
        break;
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值