h5游戏框架设计-------网络框架

MessageManager设计

  • 创建websocket
		this.socket = new egret.WebSocket();
		this.socket.addEventListener(egret.Event.CONNECT, this.onConnect, this);
		this.socket.addEventListener(egret.Event.CLOSE, this.onClose, this);
		this.socket.addEventListener(egret.IOErrorEvent.IO_ERROR, this.onError, this);
		this.socket.addEventListener(egret.ProgressEvent.SOCKET_DATA, this.onMessage, this);
		//二进制
		this.socket.type = egret.WebSocket.TYPE_BINARY;
  • 超时处理
	 	private timeOutTimer: egret.Timer;
		public connect() {
			if (!this.timeOutTimer)
				this.timeOutTimer = new egret.Timer(8000);
			this.timeOutTimer.once(egret.TimerEvent.TIMER_COMPLETE, this.onTimeOut, this);
			this.socket.connect("192.168.0.105", 8084);
		}
		private onTimeOut() {
			console.log("time out");
			this.socket.close();
			//返回登录界面
		}
  • 所有类型消息处理函数Map
		//key:消息ID value:处理函数
		private handleMap: { [key: number]: Function } = {};
		//初始化时将各个模块的消息分模块的注册到 handleType中
		private register(type: number, handler: Function) {
			if (!handler) return;
			if (this.handleMap[type]) {
				console.warn(this, type + " has already been registed to GameSocket");
			}
			this.handleMap[type] = handler;
		}
		//注销消息
		private unRegister(type: number): void {
			if (type in this.handleMap) {
				delete this.handleMap[type];
			}
			else {
				console.error(this, "Cannot find the type: " + type);
			}
		}
		//进行消息分配
		private onMessage() {
			var msg = new egret.ByteArray();
			this.socket.readBytes(msg);
			msg.position = 0;
			while (msg.readAvailable >= 4) {
				var len = msg.readShort();
	
				if (len <= 0) {
					console.log("wrong msg len!");
				}
				if (msg.readAvailable >= len - 2) {
					var cmd: any = msg.readShort();
					var pos = msg.position;
					var isHandle = this.excuteHandle(cmd, msg);
					msg.position = pos + len - 4;
				} else {
					msg.position -= 2;
					break;
				}
			}
		}
		//执行相应的消息处理函数
		private excuteHandle(cmd: number, msg) {
				if (cmd in this.handleType)
					this.handleType[cmd](msg);
				else
					console.warn(this, "No handle was found for type: " + cmd);
				}	
			}

将所有的消息根据模块进行划分,然后进行模块管理,比如在前期登录的时候用的消息接口,进入游戏不用了 可以注销掉,以减少一些内存

		//批量注册
		public registerMessageReciever(reciever: AbstractMessageReceiver): void {
			var dic: { [key: number]: Function } = reciever.collectObservers();
			for (var key in dic) {
				this.register(Number(key), dic[key]);
			}
		}
	
		public removeMessageReciver(reciever: AbstractMessageReceiver): void {
			var dic: any = reciever.collectObservers();
			for (var key in dic) {
				this.unRegister(parseInt(key));
			}
		}

AbstractMessageReceiver设计

每个模块继承AbstractMessageReceiver生成自己的消息队列

		private cmdObservers: { [key: number]: Function } = {};
		private hasCollected: boolean = false;
		/**注册命令列表**/
		protected registObservers(): void {
			throw new Error("collectObservers must be implemented by subclass");
		}
		/**获取命令观察列表**/
		public collectObservers(): any {
			if (!this.hasCollected) {
				this.registObservers();
				this.hasCollected = true;
			}
			return this.cmdObservers;
		}
		/**
	   * 注册命令及对应处理函数
	   */
		protected register(cmd: number, handler: Function): void {
			if (cmd in this.cmdObservers) {
				//egret.log("Warning  " + cmd + " has already been registed");
			}
			if (handler == null) {
				throw new Error("Cannot registe a null hanlder")
			}
			this.cmdObservers[cmd] = handler;
		}

PreTreatGCMessage

用来管理预处理模块的所有GC(服务器到客户端)消息,当初始化游戏的时候可以将该模块加载到MessageManager,当进入游戏可以将该模块注销掉,该模块的消息将不再监听,也减少一点内存

	class PreTreatGCMessage extends AbstractMessageReceiver {
		protected registObservers(): void {
			//注册消息的处理函数
			this.register(511, this.onHandShock);
			this.register(1203, this.onLoginSuccess);
		}
		//握手消息
		private onHandShock() {
			PreTreatCGMessage.CG_LOGIN();
		}
		//登录成功
		private onLoginSuccess() {
			console.log("登录成功");
		}
	}

PreTreatCGMessage

管理所有预处理模块的所有CG(客户端到服务器)消息

		class PreTreatCGMessage {
		public static CG_HAND_SHOCK() {
			var body = new egret.ByteArray();
			MessageManager.ins().sendPacket(510, body);
		}
		public static CG_LOGIN() {
			var body = new egret.ByteArray();
			body.writeUTF("1");
			body.writeUTF("1");
			body.writeUTF("");
			body.writeBoolean(false);
			body.writeInt(1);
			body.writeUTF("mozilla/5.0 (windows nt 10.0; wo");
			body.writeUTF("mozilla/5.0 (windows nt 10.0; wo");
			body.writeUTF("-1");
			body.writeUTF("1.0.0");
			body.writeUTF("zh_CN");
			MessageManager.ins().sendPacket(1201, body);
		}
}

最后再来一个单例----Singleton基类

继承SingleTon就可以实现基类不用再子类再写任何代码
可以将MessageManger继承自SingleTon

		class Singleton {
			public static ins(this: new (...args) => T): T {
				if (!(this).instance)
					(this).instance = new this();
				return (this).instance;
			}
			//销毁单例
			public static detory(this: new (...args) => T) {
				if ((this).instance) {
					delete (this).instance;
					(this).instance = null;
				}
			}
		}

你可能感兴趣的:(egret,html,网络通讯;,游戏,websocket)