JavaScript實現H5遊戲斷線自動重連的技術
斷線重連的需求
尤其是手機上,會因為網路的不穩定或者其他原因,導致使用者的socket連結斷開。這個時候如果直接讓玩家退出遊戲,重新登入,無疑是非常影響使用者體驗的事情。所以根據這個需求,就有需要程式來實現斷線後自動重連回去的技術,是使用者能夠再次快速開始遊戲進行戰鬥。
一、斷線重連原理
原來其實很簡單,就是在斷線的時候,根據使用者的點選(有些時間短的就不用點選,預設是自動重連回來),程式自動識別,是要重新整理重新進入遊戲還是幫使用者自動重連。客戶端會根據自動重連標記,幫使用者自動做事情。比如自動登陸、選角色、進入場景、請求同步後臺資料等等。
根據實現機制,大致可以分兩種實現方法。主要是遊戲內自動重連(不重新整理)和重新整理遊戲自動重連,後面會詳細講兩種實現機制,以及相關的利弊。
二、遊戲內自動重連(不重新整理)
這種是比較難的,因為不重新整理遊戲,那麼會因為一段時間的斷開遊戲,導致客戶端資料跟伺服器資料不同步了。比如怪物的位置、獲得的獎勵、進度等等。這些需要一開始就設計好,如果策劃在後期要求加這個,那幾乎是無法實現的,改動太大了。所以假設要這麼多,大概是類似下面的做法。(如果真要詳細,得一篇新的Blog了:)
1. 客戶端和服務端協定好那些資料需要客戶端自己同步
2. 斷線多久內可以自動重連(策劃以及技術上的實現來互相評估)
3. 服務端提供自動重連的協議,同時使用者斷線第一時間不應該就銷燬掉相關資料(這裡比較複雜,比如自動戰鬥是否要一直在伺服器掛著,以及其他的一些關聯操作)
4. 客戶端不重新整理遊戲,使用新介面重新連線伺服器,自動更新和同步相應的資料(比如同步怪物位置或者其他人物位置等等)
這種技術一般用於回合制之類的遊戲,一般不涉及戰鬥系統。如果arpg的話,只能短暫的時間內可以自動重連,不然的話變數太大。或者需要做一些變種,比如單純場景的怪物之類的重新整理下,但是世界boss之類的場景就得重新載入之類的特殊處理。
三、重新整理遊戲自動重連
我個人感覺這個是簡單粗暴又實用的做法。大部分遊戲都適合使用,只要一重新整理,遊戲的資料都沒了,全部重新開始,客戶端只需要根據標記來做一些自動化的操作,容易很多。,同時伺服器也不用更改,穩定也不容易出錯。唯一不好的就是使用者體驗會稍微差一些。
重連資料
字串資料:
//ip + 使用者標識 + 服id + 服名字 (資料根據自己專案情況)
var reload:string = ip + "#" + token + "#" + serverId + "#" +serverName;
//後面的reload字串都是這裡的內容
重連標識:
reload //字串
注意:重新整理只能重新整理自己的頁面。(比如在iframe裡面的時候)
Location.replace重置url重連
這種比較簡單,也不會有什麼相容性的問題。就是重連的時候,把之前的登入使用者以及服務端地址給記錄起來
通過url來附帶引數,最後再實際使用中解析出來,通過判斷屬性是否過載,
Location 物件的replace()方法:用新的文件替換當前文件。
通過傳入新的url(其實是原url + 附帶重連資料)
location.replace(oldUrl + "reload#" + reload);
是必須走url,而且還需要和原來的引數進行相容處理。在遊戲遊戲中可能是這樣的url了:
http://localhost:63342/game/index.html?reload=1&host=ws://192.168.0.10:1050/ws&token=soda1&serverId=1&serverName=本地除錯
- document.cookie
cookie 是儲存於訪問者的計算機中的變數。每當同一臺計算機通過瀏覽器請求某個頁面時,就會發送這個 cookie。你可以使用 JavaScript 來建立和取回 cookie 的值。
利用cookie的本地存放功能,也比較方便,但是會有些手機瀏覽器可能會無法讀取到。
document.cookie = "reload#" + reload;
- 使用Html5的window.localStorage
localStorage 屬性允許你訪問一個 local Storage 物件。localStorage 與 sessionStorage 相似。不同之處在於,儲存在 localStorage 裡面的資料沒有過期時間(expiration time),而儲存在 sessionStorage 裡面的資料會在瀏覽器會話(browsing session)結束時被清除,即瀏覽器關閉時。
應該注意的是,無論是 localStorage 還是 sessionStorage 中儲存的資料都僅限於該頁面的協議。
既然是H5遊戲,當然重點是使用這個了,先看下localStorage的API
。
window.localStorage.setItem("reload", reload);
讀取:
var reload = window.localStorage.getItem("reload");
- 使用Egret的本地儲存
使用Egret會更方便,他進行了封裝,H5和打包成本地都可以支援。localStorage.ts
egret.localStorage介面
//儲存資料
export let getItem:(key:string)=>string;
//刪除資料
export let removeItem:(key:string)=>void;
//將所有資料清空
export let clear:()=>void;
Web實現類WebLocalStorage.ts
namespace egret.localStorage.web {
function getItem(key:string):string {
return window.localStorage.getItem(key);
}
function setItem(key:string, value:string):boolean {
try{
window.localStorage.setItem(key, value);
return true;
}
catch(e){
egret.$warn(1047, key, value);
return false;
}
}
function removeItem(key:string):void {
window.localStorage.removeItem(key);
}
function clear():void {
window.localStorage.clear();
}
localStorage.getItem = getItem;
localStorage.setItem = setItem;
localStorage.removeItem = removeItem;
localStorage.clear = clear;
}
可以看到內部其實也是採用了window.localStorage來進行實現,同時做了一場處理,最後是通過localStorage介面進行賦值給外部呼叫。下面是實際使用方法:
//使用egret的本地存放方法做
egret.localStorage.setItem("reload",reload);
//遊戲中獲取
var reload:string = egret.localStorage.getItem("reload");
四、實際專案中處理重連機制
這裡的程式碼是重新整理之後重新進入遊戲,然後通過之前的資料(url或者本地快取)解析出相應的資料來進行判斷。
解析url
var reload:string = location.href;
本地快取獲取資料
var reload:string = egret.localStorage.getItem("reload");
console.info("reload資料:" + reload);
if(reload && reload != "")
{
var cooks:string[] = reload.split("#");
console.info("斷線重連重新整理過來的");
this.session.isReload = true;
this.session.host = cooks[0];
this.session.token = cooks[1];
this.session.serverId = Number(cooks[2]);
this.session.serverName = cooks[3];
}
通過遊戲內的變數進行判斷處理
if(this.session.isReload)
{
//開始自動重連,走額外的協議以及自動處理
}
else
{
//走正常的流程
}
最後的總結
斷線重連這裡主要是講了一些思路以及實際專案中的應用。程式碼算是偽5程式碼了,讀者應該根據自己專案實際情況來設計,做一些相應變化,原理是一樣的。
我們有一個專案是有遇到過其中的一個問題,因為一開始沒有考慮自動重連的問題,在客戶端和伺服器都沒這裡的考慮。所以沒辦法做到不重新整理遊戲來進行重連(主要是成本太大,又是arpg遊戲),最終是選擇了遊戲自己重新整理來實現的機制的。當然也會遇到一些坑,比如接入一些平臺,只能重新整理自己的html,無法重新整理平臺的html(遊戲內嵌),導致平臺的sdk的問題(影響充值、關注等等)。不過最終都是有通過變通之類的進行解決了。
相關推薦
JavaScript實現H5遊戲斷線自動重連的技術
斷線重連的需求 尤其是手機上,會因為網路的不穩定或者其他原因,導致使用者的socket連結斷開。這個時候如果直接讓玩家退出遊戲,重新登入,無疑是非常影響使用者體驗的事情。所以根據這個需求,就有需要程式來實現斷線後自動重連回去的技術,是使用者能夠再次快速開始遊戲
Node.js熱部署代碼,實現修改代碼後自動重啟服務方便實時調試
iso 用戶 使用方法 了解 super 幫助 應用 https js文件 寫PHP等腳本語言的時候,已經習慣了修改完代碼直接打開瀏覽器去查看最新的效果。而Node.js 只有在第一次引用時才會去解析腳本文件,以後都會直接訪問內存,避免重復載入,這種設計雖然有利於提高性能,
PHP連線MySql閃斷自動重連的方法
使用php作為後臺執行程式(例如簡訊群發),在cli模式下執行php,php需要連線mysql迴圈執行資料庫處理。 當mysql連線閃斷時,之後迴圈的執行將會失敗。 我們需要設計一個方法,當mysql閃斷時,可以自動重新連線,使後面的程式可以正常執行下去。 1.建立測試資料表 CREATE&nbs
SHELL指令碼實現服務宕機監控自動重啟
需要先安裝 yum install stat crontabs (本例項在centos系統下) #!/bin/bash #Shell ##根據修改檔案時間進行監控## content=`ls -l /tmp/log.txt | awk '{ print $5 }'`
關於javaScript實現select下拉框自動展開
我本來的目的:是想實現滑鼠移動到select下拉框上,下拉框自動展開。 原先思路:使用onmouseover()滑鼠事件呼叫一個openSelect()函式,函式中呼叫onclick()方法,以為就可以了(程式碼如下),我想得太簡單了。 <head&g
JavaScript實現的遊戲們
伴隨Ajax與網頁遊戲的崛起,曾幾何時JavaScript也成了遊戲開發時可供選擇的技術之一,文字僅列舉數項由JavaScript技術實現的web小遊戲(不含網遊),聊作參考之用。 傳說中的馬里奧網頁版,一比一實現了紅白機時代超級馬里奧中所有功能與關卡,精細程度不遜原
微信小程式 實現websocket長連線 以及斷開連線之後自動重連
app.js let socketMsgQueue = [] let isLoading = false App({ globalData: { userInfo: null, localSocket: {}, callback: function () {} },
spring-websocket --WebSocketStompClient端實現自動重連
轉自https://blog.csdn.net/u013174217/article/details/53376793websocketstompclient端實現和服務端建立連線和通訊之後,如果服務端斷開或重啟,client端需要實現自動定時重連機制。查閱了官網和一些資料沒
Jboss數據庫連接斷開自動重連
jbossJboss默認配置是數據庫連接端口後,服務就會出現異常,無法訪問,此時必須重啟Jboss服務才能重新連接上數據庫。在jboss/server/defult/deploy/oracle-ds.xml中加入:<new-connection-sql>select 1 from dual<
[轉]樹莓派.設置自動重連WiFi
system init.d defaults href ans start class ati call 由於不可知的原因,有可能會導致樹莓派失去連接,這時候需要重新連接WiFi。 自動重連的原理是,定期查看是否斷網,如果斷網了重啟WiFi,參考的文章是這篇,第一步略有修
Delphi使用ADO連接網絡數據庫,斷網後重連問題
無法 create exit eat bject sender class exce cep 原始文章: https://blog.csdn.net/blog_jihq/article/details/11737699# 使用TADOConnection對象連接網絡數據庫
TCP自動重連
list save Coding locale [] ext eat blocking one 網上模板: public class Socket_wrapper { public static Socket theSocket = nul
【HP-Socket沉思錄】在 OnClose 中自動重連
HP-Socket 版本 5.3.2 其實這裡是取了個巧,因為並不是真正意義上的在 OnClose 中。由於同一個連線的事件是序列的,所以 OnClose 事件不完成 socket 的狀態始終懸置。 可以在 OnClose 中
藍芽自動重連
1利用系統中的自動重連 getDevice().connectGatt(context, autoConnect, coreGattCallback); private BleGattCal
Java NIO SocketChannel客戶端例子(支援連線失敗後自動重連)
這兩天想找找標題裡說的這個示例程式碼,發現網上這麼多教程,連怎麼樣實現自動重連都不講,所以把自己寫的例子貼上來。僅僅使用遞迴,不使用多執行緒,就可以實現初步的目的: import java.io.IOException; import java.net.ConnectExc
jdbc C3P0容錯和自動重連
1)C3P0容錯和自動重連與以下配置引數有關: breakAfterAcquireFailure :true表示pool向資料庫請求連線失敗後標記整個pool為block並close,就算後端資料庫恢復正常也不進行重連,客戶端對pool的請求都拒絕掉。fals
設定網路對映後,電腦重啟後自動重連
1. 利用批處理檔案來自動對映 ① 首先製作自動對映網路驅動器批處理檔案; ② 利用Net Use命令,其基本格式如下: NET USE [devicename | *] [\\computername\sharename[\volume] [p
SecureCRT自動重連伺服器的解決方法
在secureCRT上登入時,一段時間不用的話會自動斷開,必須重新連線,有點麻煩,對於密碼為動態的密碼的情況就更為不方便,為了解決此問題,有兩種方案: 1、修改伺服器端的 /etc/profile 檔案
(六)、ZooKeeper自動重連
在一套分散式的online services系統中,各service通常不會放在一臺伺服器上,而是通過Zookeeper這樣的東西,將自己的service資訊註冊到上面,service的使用者通過Zookeeper來發現各service的資訊,從而可以將req
activeMQ 自動重連機制
在使用activeMQ的時候(沒有整合spring),發現當broker掛掉或者重啟的時候,consumer就會斷開,不會在次嘗試去接受訊息, (使用spring整合activeMQ)會解決這個問題. 如果說你不想使用spring,那麼接下來告訴你該怎麼辦. 在apache