Intro
如果您沒有看上一篇文章,建議您先移步到這裡查看第一部分 上一次主要解決了基本的數據增量同步的問題,但仍然存在一些問題。 可能存在的主要問題:
針對以上可能出現的這兩個問題,需要對數據進行校驗並且數據量超過一定量時進行分批量傳輸, 本文將著手解決 數據校驗 和 數據分批次傳輸 這兩個問題。
同步流程概覽
結合之前的同步流程,加上數據校驗和分批次傳輸數據,大概流程如下: 客戶端調用服務器端的 Pull
接口從服務器端拉取數據, 如果本地版本號等於服務器端最新版本號,則已更新的最新版本, 如果本地版本小於服務器端最新的版本號,則拉取需要更新的數據,服務器端返回數據的同時會返回本地傳輸的數據的一個校驗值, 客戶端獲取到服務器端響應時先根據接收到的數據計算校驗值,計算出來之後與服務器端返回的校驗值進行比較, 如果本地計算的校驗值與服務器端返回的校驗值一致則進行更新客戶端本地數據,不一致則視為無效數據,重新請求 Pull
接口。
更新到最新版本之後,判斷本地是否存在未提交的版本,如果本地不存在修改則本次數據同步完成,如果本地存在修改,則提交本地修改,提交本地數據的之前要先計算傳輸數據的校驗值,校驗值和本地數據一起傳給服務器端 Push
接口。 服務器端 Push
接收到客戶端請求之後需要進行數據校驗,根據傳輸的數據計算校驗值並與客戶端傳的校驗值比較, 如果兩個值不一致,則視為數據在傳輸過程中發生丟失或是異常數據,則不處理並返回客戶端,本次請求屬於異常請求。 如果兩個值一致,再進行數據處理,處理結束之後,數據會有一個返回狀態和其他必要的屬性,根據數據計算校驗值,與從服務器拉取數據時類似,不再贅述, 客戶端數據校驗通過之後,根據服務器端處理狀態進行本地數據的更新。
下面展示添加數據校驗後的主要流程圖:
服務器端獲取數據:
客戶端拉取數據:
服務器端更新數據:
客戶端推送更新數據:
數據校驗
數據校驗,我們用的是MD5進行校驗,取傳輸數據的MD5,使用MD5有兩方面的考慮: 一方面因為MD5生成的字符串不算太長,不會影響傳輸的數據量, 另一方面也是因為MD5比較通用一些,APP端實現起來也比較方便。
數據分批傳輸
數據分批次傳輸,自己感覺這裡實現的比較 LOW ,這裡類似於網站上的分頁,沒想到更好的解決方案,期待大神分享更好的解決方案。 返回客戶端 當前請求數據頁碼索引 和 本次數據傳輸總頁數,如果頁碼索引小於總頁數,則頁碼索引+1,再請求一次接口知道返回的頁碼索引等於總頁數。
Summary
數據轉MD5的時候,再次踩了一個坑, 開始是這樣做的,用MD5算法計算出字節數組,然後使用 System.Text.Encoding.UTF8.GetString()
方法轉換成字符串,結果在調試的時候就傻逼了,獲取到的字符串是亂碼、亂碼、亂碼。。。【No zuo no die】
下面祭出我鮮血淌過的代碼【笑Cry】
1 /// <summary> 2 /// 對象轉換為MD5字符串 3 /// </summary> 4 /// <param name="obj">對象</param> 5 /// <param name="isLowwer">是否是小寫</param> 6 /// <returns></returns> 7 public static string ToMD5String(this object obj, bool isLowwer = false) 8 { 9 if (obj == null) 10 { 11 return ""; 12 } 13 //創建MD5對象 14 MD5 md5 = new MD5CryptoServiceProvider(); 15 byte[] byteArray = null; 16 using (MemoryStream ms = new MemoryStream()) 17 { 18 new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(ms, obj); 19 byteArray = ms.ToArray(); 20 } 21 //計算指定字節數組的哈希值 22 byte[] bMD5 = md5.ComputeHash(byteArray); 23 //釋放加密服務提供類的所有資源 24 md5.Clear(); 25 System.Text.StringBuilder sbMD5Pwd = new System.Text.StringBuilder(); 26 if (isLowwer) 27 { 28 for (int i = 0; i < bMD5.Length; i++) 29 { 30 //將每個字節數據轉換為2位小寫的16進制的字符 31 sbMD5Pwd.Append(bMD5[i].ToString("x2")); 32 } 33 } 34 else 35 { 36 for (int i = 0; i < bMD5.Length; i++) 37 { 38 //將每個字節數據轉換為2位大寫的16進制的字符 39 sbMD5Pwd.Append(bMD5[i].ToString("X2")); 40 } 41 } 42 return sbMD5Pwd.ToString(); 43 }
最後提供整個同步流程設計的流程圖,點我下載
另如果你有別的方案歡迎共同討論,希望大神看到能給出自己的看法和意見,有不正確的地方還希望能夠告知。