cocoscreator websocket示例

const { ccclass, property } = cc._decorator;

/**
 * 網絡連接狀態
 */
export enum NetWorkState {
    NetWorkState_NONE,
    NetWorkState_CONNECTING,
    NetWorkState_CONNECTED,
    NetWorkState_ERROR,
    NetWorkState_CLOSE,
    NetWorkState_TIMEOUT,
    NetWorkState_MAX
}

@ccclass
export class NetWork {
    private static m_sInstance: NetWork = null;

    private m_cDstIP: string = "";
    private m_pSocket: WebSocket = null;
    private m_eNetWorkState: NetWorkState = NetWorkState.NetWorkState_NONE;
    private m_vDelegates: any[] = [];
    private m_bReciveHeadMsg: boolean = false;
    private m_nHeartbeatNum: any = -1; // 心跳包句柄
    private m_nConnectNum: any = -1; // 重連句柄
    private m_bIsSendHeard: boolean = true;
    private m_vMessageCallBack: any[] = [];
    private m_nConnectCount: number = 0;//當前連接的次數(用於判斷重連的提示,比如連接三次都沒連接上就提示玩家檢查網絡)
    private m_bIsHoldClose: boolean = false;//是否是手動關閉

    private m_nforgroundCount: number = -1;
    private m_nConnectGameServerNum: number = -1;//連接邏輯服務器的句柄
    private m_nConnectGameServerNum_1: number = -1;//連接邏輯服務器的句柄


    /**
     * 連接地址
     */
    private socketIP: string = "ws://192.168.0.127:8080";


    public getSocketIP(): string {
        return this.socketIP;
    }



    /**
     * 設置是否自動連接
     * @param is 是否自動連接
     */
    public setAutoConnect(is: boolean): void {
        this.m_bIsAutoConnect = is;
    }

    private forgroundConnect(): void {
        if (this.m_nforgroundCount != -1) {
            clearTimeout(this.m_nforgroundCount);
        }
        this.m_nforgroundCount = setTimeout(() => {
            this.socketIP && this.connect(this.socketIP, false);
        }, 500);
    }

    /**
     * 應用程序進入前臺
     */
    private applocationEnterForeground(): void {
        console.log("applocationEnterForeground");
        this.forgroundConnect();

    }
    /**
     * 應用程序進入後臺
     */
    private applocationEnterBackground(): void {
        console.log("applocationEnterBackground");
        this.closeNetWork(true);
    }

    public static getInstance(): NetWork {
        if (!this.m_sInstance) {
            this.m_sInstance = new NetWork();
            this.m_sInstance.init();
        }
        return this.m_sInstance;
    }

    private init(): void {

        this.m_eNetWorkState = NetWorkState.NetWorkState_NONE;
        this.m_bReciveHeadMsg = false;
        this.m_nHeartbeatNum = -1;
        this.m_nConnectNum = -1;

        cc.game.on(cc.game.EVENT_SHOW, this.applocationEnterForeground, this);
        cc.game.on(cc.game.EVENT_HIDE, this.applocationEnterBackground, this);
    }
    /**
     * 獲取當前重連的次數
     */
    public getConnectCount(): number {
        return this.m_nConnectCount;
    }

    /**
     * 返回當前網絡狀態
     */
    public getNetWorkState(): NetWorkState {
        return this.m_eNetWorkState;
    }

    /**
     * 網絡是否已經連接
     */
    public isConnect(): boolean {
        return this.getNetWorkState() == NetWorkState.NetWorkState_CONNECTED;
    }


    /**
     * 把自己添加到隊列裏,用於接受消息,要實現
     * public onMsg(msg: any):boolean{....}方法才能接收到消息
     * 如果你確定這個消息只在你這處理,就return true;否則return false;
     * @param delegate 需要接收消息的本身
     */
    public addDelegate(delegate: any): void {
        this.m_vDelegates.push(delegate);
    }

    /**
     * 把自己從隊列裏移除
     * @param delegate 添加時傳入的對象本身
     */
    public removeDelegate(delegate: any): void {
        for (let idx = 0; idx < this.m_vDelegates.length; idx++) {
            if (this.m_vDelegates[idx] == delegate) {
                this.m_vDelegates.splice(idx, 1);
                break;
            }
        }
    }

    /**
     * 手動關閉連接
     */
    public closeNetWork(isHoldClose): void {
        this.m_cDstIP = "";
        let state = this.getNetWorkState()
        console.log("手動關閉 state : " , state);
        this.m_bIsHoldClose = isHoldClose;
        if (this.m_pSocket) {
           this.m_pSocket.onopen = () => { };
           this.m_pSocket.onclose = () => { };
           this.m_pSocket.onerror = () => { };
           this.m_pSocket.onmessage = () => { };
           this.m_pSocket.close();
        }
        this.onClose(null);
    }


    /**
     * 延時重新連接
     */
    private timeOutConnect(): void {
        this.m_pSocket && this.closeNetWork(false);
        if (!this.m_bIsHoldClose) {
            if (this.m_nConnectNum != -1) {
                clearTimeout(this.m_nConnectNum);
            }
            this.m_nConnectNum = setTimeout(() => {
                if (!this.connect(this.socketIP, false)) {
                    console.log("cancel doConnect.");
                }
            }, clientDefine.clientDefine_connect_timeout);
        }
    }

    /**
     * 開始連接並賦值ip
     * @param dstIP ip ws://127.0.0.1:8080/
     * @param isSendHeard 是否發送心跳包
     * @example 
     * this.connect("ws://127.0.0.1:8080/", false);
     */
    public connect(dstIP: string, isSendHeard: boolean): boolean {
        this.m_cDstIP = dstIP;
        this.m_bIsSendHeard = isSendHeard;
        return this.doConnect();
    }

    /**
     * 使用上次ip繼續連接
     */
    public doConnect(): boolean {
        if (this.getNetWorkState() == NetWorkState.NetWorkState_CONNECTED || this.getNetWorkState() == NetWorkState.NetWorkState_CONNECTING) {
            cc.error("already connect to server. state = " + this.getNetWorkState());
            return false;
        }
        if (!(this.m_cDstIP && this.m_cDstIP.length > 0)) {
            cc.error("dstIP is null.");
            return false;
        }
        this.m_bIsHoldClose = false;
        console.log("connect to server. dstIP = " + this.m_cDstIP);
        this.m_nConnectCount++;
        this.m_eNetWorkState = NetWorkState.NetWorkState_CONNECTING;
        this.m_pSocket = new WebSocket(this.m_cDstIP);
        //this.m_pSocket.binaryType = "arraybuffer";//設置發送接收二進制
        this.m_pSocket.onopen = this.onOpen.bind(this);
        this.m_pSocket.onclose = this.onClose.bind(this);
        this.m_pSocket.onerror = this.onError.bind(this);
        this.m_pSocket.onmessage = this.onMessage.bind(this);
        if (this.m_nConnectGameServerNum_1 != -1) {
            clearTimeout(this.m_nConnectGameServerNum_1);
        }
        this.m_nConnectGameServerNum_1 = setTimeout(() => {
            if (!this.isConnect()) {
                this.m_pSocket && this.closeNetWork(false);
            }
        }, clientDefine.clientDefine_timeout);

        return true;
    }

    private onOpen(ev): void {
        console.log(" open ");

        if (this.m_nConnectGameServerNum_1 != -1) {
            clearTimeout(this.m_nConnectGameServerNum_1);
        }

        this.m_bIsOnConnectGameServer = false;
        this.m_nConnectCount = 0;
        this.m_eNetWorkState = NetWorkState.NetWorkState_CONNECTED;
        let pEvent = new cc.Event.EventCustom(clientDefine.clientDefine_open, true);
        cc.systemEvent.dispatchEvent(pEvent);

        this.m_bIsSendHeard && this.doSendHeadBet();

    }
    private onClose(ev): void {
        console.log(" close ");

        if (this.m_nConnectGameServerNum_1 != -1) {
            clearTimeout(this.m_nConnectGameServerNum_1);
        }

        this.m_pSocket = null;
        this.m_eNetWorkState = NetWorkState.NetWorkState_CLOSE;
        let pEvent = new cc.Event.EventCustom(clientDefine.clientDefine_close, true);
        cc.systemEvent.dispatchEvent(pEvent);
        this.timeOutConnect();
    }
    private onError(ev): void {
        console.log(" error ");

        if (this.m_nConnectGameServerNum_1 != -1) {
            clearTimeout(this.m_nConnectGameServerNum_1);
        }

        this.m_eNetWorkState = NetWorkState.NetWorkState_ERROR;
        let pEvent = new cc.Event.EventCustom(clientDefine.clientDefine_failed, true);
        cc.systemEvent.dispatchEvent(pEvent);
    }
    private onMessage(ev): void {
        let message = JSON.parse(ev.data);
        if(this.m_vMessageCallBack[message.command]) {
            this.m_vMessageCallBack[message.command](message);
            this.m_vMessageCallBack[message.command] = null;
        } else {
            for (let idx = 0; idx < this.m_vDelegates.length; idx++) {
                if (this.m_vDelegates[idx] && typeof (this.m_vDelegates[idx].onMsg) === "function"
                        && this.m_vDelegates[idx].onMsg(message)) {
                    break;
                }
            }
        }
    }

    /**
     * 發送消息
     * @param msgBody 需要發送的消息
     * @param command 消息ID
     */
    public sendMsg(msgBody: object, command: number, responseCommand: number = null, callBack: Function = null): boolean {
        if (this.isConnect()) {
            msgBody.command = command;
            this.m_pSocket.send(msgBody);
            callBack && (this.m_vMessageCallBack[responseCommand] = callBack);
            return true;
        } else {
            console.log("send msg error. state = " + this.getNetWorkState());
        }
        return false;
    }

    /**
     * 發送心跳包
     */
    private doSendHeadBet(): void {
        if (!this.isConnect()) {
            cc.error("doSendHeadBet error. netWork state = " + this.getNetWorkState());
            this.timeOutConnect();
            return;
        }
        this.m_bReciveHeadMsg = false;

        this.sendMsg({},心跳消息ID);

        console.log("send head msg.");
        if (this.m_nHeartbeatNum != -1) {
            clearTimeout(this.m_nHeartbeatNum);
        }
        this.m_nHeartbeatNum = setTimeout(() => {
            if (this.m_bReciveHeadMsg) {
                this.doSendHeadBet();
            } else {
                this.timeOutConnect();
            }
        }, clientDefine.clientDefine_headmsg_timeout);
    }

}



監聽消息

NetWork.getInstance().addDelegate(this);

 移除監聽 *(在節點註銷的時候必須調用)

 

NetWork.getInstance().removeDelegate(this);

重寫onMsg函數接收消息

 /**
    * 收消息
    * @param message 消息
    */
    public onMsg(message: any): boolean {
        switch (message.command) {
            case 消息ID: {
                
                return true; // 返回reture表示消息只在這裏處理,不在往下傳遞
            }
        }
        return false;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章