mysql4.redis模塊-->redis框架劃分1.webserver?..."/>
您好,登錄后才能下訂單哦!
一、項目劃分
框架依賴的模塊
1.高性能webserver--express模塊 熱更新 語音對話
2.websocket模塊--ws
3.mysql模塊-->mysql
4.redis模塊-->redis
框架劃分
1.webserver作用就是用來上傳下載,獲取配置信息,更新等.
通過web接入第三方的sdk。
2.gateway網關服務器,
(1)用來接收所有用戶的長連接,轉發(fā)用戶請求
(2)連接游戲服務器轉發(fā)服務器回應
(3)安全防護,過濾非法的數據包隔離游戲服務器免受客戶***.
3.用戶中心服務器: 用來管理這個用戶的賬號信息.這個用戶信息
管理號,可以在進行這個平臺的其他游戲.
4.系統(tǒng)服務: 處理用戶和系統(tǒng)進行交互:每日登錄,郵件,兌換東西等等.
比如你要做一個活動,這個就是用戶和服務器單獨交互.不會涉及其他用戶.
5.游戲服務器:他涉及到多個用戶之間的交互,處理不同游戲的服務.
每個服務又是一個進程,
數據庫劃分
1.后臺數據庫,分為兩個.第一個數據庫用來存放用戶數據,大家公用的,
第二個是每個游戲都有一個游戲數據庫。
2.為了訪問速度的提高,把常用的數據緩存到redis服務器,
redis緩沖中心:也是兩個:用戶redis,和游戲數據redis.
3.數據庫是所有進程都公用的.
3rd/utils/netbus模塊
1.3rd存放第三方的js代碼庫
2.utils存放所有的公共模塊
3.netbus模塊,為所有長連接服務器所公用,支持websocket
TCP socket 二進制和json協(xié)議。
二、日志 TCPsocket和websocket模塊封裝支持
Log日志代碼
1.log日志是重要的服務器手段
2.log寫日志必須是異步的
3.log日志能夠方便的定向到對應的服務器里去
4.log日志分登記和顏色
5.調試時全部打印到標準的輸出文件,上線時在輸出在文件
6.創(chuàng)建一個output文件夾存放輸出的日志.
7.日志分級,如一般信息,警告信息,錯誤信息.
8.把重要信息保存到log,比如你充值了10元.
驗證數據的合法性
1.tcp socket收到的數據必須是Buffer類型
2.ws socket json數據協(xié)議下收到的類型必須是字符串
3.ws socket buf數據協(xié)議下收到的類型必須是buffer
三、協(xié)議管理模塊
1.協(xié)議規(guī)定是: 服務號,命令號,數據部分
2.提供協(xié)議解碼 cmd[0]服務號,cmd[1]命令號,cmd[2]body三個部分
3.提供協(xié)議編碼函數轉json字符 或者 buff二進制(2字節(jié)2字節(jié)+body);
4提供協(xié)議服務端buf×××注冊函數
5.同時支持json和二進制,通過客戶端連接自己選擇
6.協(xié)議加密和解密也可以加入到這個模塊
先編碼在加密 —— 先解密在解碼
一般只需要支持一種協(xié)議即可.
四、netbus服務管理模塊
1.當netbus收到數據包的時候,需要把包分發(fā)給對應的服務來進行處理
2.service_manager(mg管理)
3.所有服務的管理模塊,所有的服務都注冊到這里
4.netbus收到數據,玩家掉線等,都進入它,通知對應的服務
5.提供服務模塊注冊函數,編寫模板服務編寫
6.轉發(fā)到對應的服務后,使用decode_cmd 加密命令
7.告訴所有的service鏈接丟失
五、creator支持websocket_http支持buf和json協(xié)議
1.creator使用websocket和服務器進行聯(lián)機,因為本身creator
本身是h6的,所以
2.ArrayBuffer.DataView,utf8,string字節(jié)長度,DataView讀/寫字符串
ArrayBuffer沒有Buffer模塊這么多接口,比如readUInt16LE這些.
這個時候就需要借助DataView.
他有一個參數,這個參數是可選的。
如果為 false 或未定義,則寫入big-endian(大尾) 值;
否則應寫入 little-endia(小尾) 值。
var buf = new ArrayBuffer(10); //無法直接操作數據 借助DataView var dataview = new DataView(buf); //在第0個字節(jié)寫入100 8一個字節(jié)沒有大小尾 dataview.setUint8(0,100); var value = dataview.getUint8(0); console.log(value);
而DataView只能處理數,沒辦法處理字符串.需要擴展DataView
//寫入utf8字符串 DataView.prototype.write_utf8 = function(offset,str){ var now = offset; var dataview = this; for (var i = 0; i < str.length; i++) { var charcode = str.charCodeAt(i); if (charcode < 0x80) { dataview.setUint8(now, charcode); now ++; } else if (charcode < 0x800) { dataview.setUint8(now, (0xc0 | (charcode >> 6))); now ++; dataview.setUint8(now, 0x80 | (charcode & 0x3f)); now ++; } else if (charcode < 0xd800 || charcode >= 0xe000) { dataview.setUint8(now, 0xe0 | (charcode >> 12)); now ++; dataview.setUint8(now, 0x80 | ((charcode>>6) & 0x3f)); now ++; dataview.setUint8(now, 0x80 | (charcode & 0x3f)); now ++; } // surrogate pair else { i ++; charcode = 0x10000 + (((charcode & 0x3ff)<<10) | (str.charCodeAt(i) & 0x3ff)); dataview.setUint8(now, 0xf0 | (charcode >>18)); now ++; dataview.setUint8(now, 0x80 | ((charcode>>12) & 0x3f)); now ++; dataview.setUint8(now, 0x80 | ((charcode>>6) & 0x3f)); now ++; dataview.setUint8(now, 0x80 | (charcode & 0x3f)); now ++; } } } //讀取utf8字符串 DataView.prototype.read_utf8 = function(offset,byte_length){ var out,i,len,c; var char2,char3; var dataview = this; //輸出 out = ""; len = byte_length; i = offset; while(i < len){ c = dataview.getUint8(i); i++; //這個字符串右移4位 判斷這個位的值 switch(c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: //Unicode 編碼轉為一個字符 //例如他是十進制65 則會轉成ACSLL 'A' out += String.fromCharCode(i); break; case 12: case 13: char2 = array[i++]; out += String.fromCharCode(((c & 0x1F)<<6) | (char2 & 0x3F)); break; case 14: char2 = dataview.getUint8(i); i++; char3 = dataview.getUint8(i); i++; out += String.fromCharCode(((c & 0x0F)<<12)| ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; }//end switch } }
封裝websocket模塊
//websocket模塊封裝 var proto = require("proto_mgr"); console.log("proto:",proto); var websocket = { sock: null, serivces_handler: null, //當有消息來的時候回調函數 proto_type: 0, //協(xié)議類型 is_commected: false,//是否連接 _on_opened: function(event){ console.log("ws connect server success!"); this.is_commected = true; }, _on_recv_data: function(strbufdata){ if(!this.serivces_handler){ console.log("not find serivces_handler"); return; } //獲取命令 var cmd = proto.decode_cmd(this.proto_type,strbufdata); if(!cmd){ console.log("websocket.js(25) cmd invaild!"); return; } var stype = cmd[0]; if(this.serivces_handler[stype]){ this.serivces_handler[stype](cmd[0],cmd[1],cmd[2]); } }, _on_socket_close: function(event){ if(this.sock){ this.close(); } }, _on_socket_err: function(event){ this.close(); }, connect: function(url,proto_type){ this.sock = new WebSocket(url); this.sock.onopen = this._on_opened.bind(this); this.sock.onmessage = this._on_recv_data.bind(this); this.sock.onclose = this._on_socket_close.bind(this); this.sock.onerror = this._on_socket_err.bind(this); this.proto_type = proto_type; }, send_cmd: function(stype,ctype,body){ if(!this.sock || !this.is_commected){ console.log("send commind error!"); return; } var buf = proto.encode_cmd(this.proto_type,stype,ctype,body); this.sock.send(buf); }, close: function(){ this.is_commected = false; if(this.sock !== null){ this.sock.close(); this.sock = null; } }, regist_services_handler: function(serivces_handler){ this.serivces_handler = serivces_handler; }, } //選擇啟動協(xié)議 //使用json 連接到服務 //websocket.connect("ws://127.0.0.1:6081/ws",proto.PROTO_JSON); //使用二進制連接到服務 //websocket.connect("ws://127.0.0.1:6083/ws",proto.PROTO_BUF); module.exports = websocket;
封裝http模塊
//http 模塊 var http = { //get請求 用于網頁 文本 get: function(url, path, params,callback){ //獲取XMLHTpRequest實例 var xhr = cc.loader.getXMLHttpRequest(); xhr.timeout = 5000; var requestURL = url + path; //添加變量 if(params){ requestURL = requestURL + "?" + params; } //http或https請求必須通過open方法初始化 //必須在發(fā)送請求前調用 //1:請求方法,2url,3ture就是異步請求 false阻塞 //4用戶名 5密碼 xhr.open("GET",requestURL,true); //true模擬器,手機 false web if(cc.sys.isNative){ //設置請求頭 信息 xhr.setRequestHeader("Accept-Encoding","gzip,deflate","text/html;charset=UTF-8"); } //readystate 是http的請求狀態(tài) 當XMLHttpRequest //初次創(chuàng)建時,這個屬性是0,直到接收到完整的HTTP響應 //這個值增加到 4。 //1是open方法被調用,send方法未調用 //2是send方法被調用,HTTP請求到達web服務器 //3是所有響應頭部都已經接收到。響應體開始接收但未完成。 //4是HTTP響應已經完成接收 xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)){ //輸出響應長度 和 正文 console.log("http res("+xhr.responseText.length+"):"+xhr.responseText); try{ var ret = xhr.responseText; if(callback !== null){ //把響應信息 傳給回調函數 callback(null,ret); } return; }catch(e){ //錯誤處理 把錯誤信息傳給回調 callback(e,null); }//end catch }//end if else{ //這里就是請求錯誤 傳給callback //請求狀態(tài) 和 狀態(tài)碼 callback(xhr.readyState+":"+xhr.status,null); }//end else }; xhr.send(); return xhr; }, //用于上傳 body就是上傳體 post: function(url,path,params,body,callback){ var xhr = cc.loader.getXMLHttpRequest(); xhr.timeout = 5000; var requestURL = url + path; if(params){ requestURL = requestURL + "?" + params; } xhr.open("POST",requestURL,true); if(cc.sys.isNative){ xhr.setRequestHeader("Accept-Encoding","gzip,deflate","text/html;charset=UTF-8"); } //判斷是否有body if(body){ //在發(fā)送到服務器之前,所有字符都會進行編碼 xhr.setRequestHeader("Content-Type","application/x-www-form=urlencoded"); //長度 xhr.setRequestHeader("Content-Length",body.length); } xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)){ try{ var ret = xhr.responseText; if(callback !== null){ //把響應信息 傳給回調函數 callback(null,ret); } return; }catch(e){ //錯誤處理 把錯誤信息傳給回調 callback(e,null); }//end catch }//end if else{ //這里就是請求錯誤 傳給callback //請求狀態(tài) 和 狀態(tài)碼 callback(xhr.readyState+":"+xhr.status,null); }//end else }; if(body){ xhr.sned(body); } return xhr; }, //用于下載 文件 二進制文件 download: function(url,path,params,callback){ var xhr = cc.loader.getXMLHttpRequest(); xhr.timeout = 5000; var requestURL = url + path; if(params){ requestURL = requestURL + "?" + params; } //響應類型 xhr.responseType = "arraybuffer"; xhr.open("GET",requestURL,true); if(cc.sys.isNative){ xhr.setRequestHeader("Accept-Encoding","gzip,deflate","text/html;charset=UTF-8"); } xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)){ var buffer = xhr.response; var dataview = new DataView(buffer); //8 位無符號整數值的類型化數組 var ints = new Uint8Array(buffer.byteLength); for(var i = 0;i < ints.length; i++){ //獲取response 二進制數據 ints[i] = dataview.getUint8(i); } callback(null,ints); }else{ callback(xhr.readyState+":"+xhr.status,null); }//end else }; xhr.send(); return xhr; }, }; module.exports = http;
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。