《Android 即時通訊開發小結》基於IM Andriod 開發的各種常見問題,結合網易雲信即時通訊技術的實踐,對IM開發做一個全面的總結。
相關推薦閱讀
建立安全連線
安全性是 IM 軟體的另一個硬需求。訊息傳遞時如果通訊資料如果被第三方擷取,要能保證別人不能獲取到真實內容。安全連線的過程可以參考 HTTPS 的方式,由伺服器將證書下發給客戶端,客戶端產生一個對稱的金鑰,並通過伺服器證書加密後交給伺服器,之後的通訊就全部使用這個對稱的金鑰來加密。當然,這裡有兩點需要和 HTTPS 有所區別,第一是證書的獲取方式,HTTPS 中是由專門機構去驗證證書合法性的,IM 的客戶端肯定不會這麼去做,為了防止獲取證書的過程被人截獲,然後篡改證書,可行的方式是直接在客戶端安裝包中直接把證書打進去,該證書可以隨著客戶端軟體升級一起升級,也可以在加密連線之後通過協議升級。第二個問題是對稱加密演算法的選擇,因為金鑰的生命週期是跟隨一次連線的,時間並不長,而移動 App 對於電量消耗非常敏感,因此加密演算法應儘量選擇較為簡單的型別,例如 RC4。
心 跳
心跳可以分為 TCP 的協議層心跳和 App 的應用層心跳。一般我們都使用應用層心跳,一來便於伺服器擴充套件(比如哪天我們可以換成 UDP 來傳),二則是可以更靈活控制心跳間隔。
心跳協議僅僅是用來連線保活,其內容應當儘量精簡,除了包頭中必要的部分,包體的可選包頭都不存在。
對於不同的網路環境,心跳可以採用不同的時間間隔。在不同網路環境下,間隔的選擇可以參考微信智慧心跳方案。
斷線重連
客戶端掉線的原因無非兩種,客戶端網路掛了,伺服器掛了。客戶端網路掛了也分兩種,一種是本機就能感知到的網路連線斷開,另一種是本機網路是好的,但網際網路連線是不同的,對應到 Android API上,就是 NetworkInfo 的 isAvailable 和 isConnected。當然這個地方的 isConnected 不一定可靠,因為它是靠連制定伺服器來確定的,那個伺服器誰知道有沒有問題。
掉線後,根據不同的狀態需要選擇不同的重連間隔。如果是本地網路出錯,並不需要定時去重連,這時只需要監聽網路狀態,等到網路恢復後重連即可。如果網路變化非常頻繁,特別是 App 處在後臺執行時,對於重連也可以加上一定的頻率控制,在保證一定訊息實時性的同時,避免造成過多的電量消耗。
而如果掉線是因為本機網路連不通網際網路,或者是伺服器掛了,重連間隔的選擇就非常重要了。
首先,如果程式是在前臺,使用者正在使用我們的 App,重連間隔應更加頻繁,使得使用者反饋更加及時,如果程式處於後臺執行,則為了省電,可以適當延長重連間隔。
其次,隨著重連次數的增加,說明伺服器短時間內恢復的可能性逐漸降低,重連間隔也應隨之延長(倍數增長)。但應該設定一個最大的重連間隔,當到達最大間隔時,不再增加。
第三,重連間隔的增加不應當是固定的,而應該增加一個隨機退避策略。以免如果是伺服器當機造成掉線,所有客戶端的重連時間點都是一樣的,當伺服器恢復後,同一個時間點所有客戶端同時連線伺服器,造成伺服器不堪擁堵,再次當機。活生生的例子請參考環信去年的當機時間。
總結起來,重連間隔可表述如下:
多媒體資料管理
IM 系統中另一個重頭戲是多媒體資料。由於行動網路比較慢,流量又貴,在移動端針對這些問題必須要做一些處理。在上傳時,儘量減少上傳時間,在下載時,能讓使用者儘快看到內容。同時,儘量節省流量,減少不必要的流量消耗。
文字訊息因為比較小,可以直接通過長連線傳輸。但對於多媒體檔案,通過長連線來傳輸則不合適,長連線伺服器不會對大檔案傳輸做針對性優化,大量的多媒體檔案資料會直接搶佔其他信令訊息和文字訊息的貸款資源。因此,多媒體訊息會通過另外的通道,到專門的檔案伺服器存取。
在下載時,對於不同的網路環境,可以採用不同的預取策略。在 WiFi 環境下,由於無需考慮流量問題,在收到訊息後,我們就能立即把包含的多媒體檔案下載下來。而在行動網路中,則應當等到使用者真正看到該多媒體訊息時,才去下載。
圖 片
上傳時,現在手機攝像頭的畫素動輒上千萬,一張圖片隨隨便便就好幾M,然而,通過 IM 軟體傳輸的圖片,通常對於質量要求並不會太高,如果我們直接將好幾M的圖片直接上傳,往往費力又不討好。在上傳之前,將圖片畫素降低,並進行壓縮,可以明顯的減少上傳轉菊花的時間,減少使用者流量消耗。如果使用者確實要求圖片質量,則提供一個原圖選項。
如果是使用 http 上傳,大檔案會被分成多個資料塊上傳,前一個資料塊傳輸成功後,再傳輸下一個。斷線重傳時,也是以資料塊作為最小重傳單元。針對不同的網路型別,資料塊大小不同。在較好網路下(wifi/4g/3g),資料塊可以比較大,這樣可以減少互動時間,加快傳輸熟讀,而在弱網環境,資料塊應當設定的比較小,以降低傳輸失敗概率,減少重傳流量消耗。
使用 http 上傳的另一個優化技術是使用 pipeline。在不使用 pipeline 時,上傳一個資料塊需要等到前一個資料塊傳輸成功才行,資料通道是單工的。使用pipeline則可以將資料通道變為雙工的,一個資料塊傳輸完成後,不必等到回包,就能直接上傳下一個資料包,能節省一次資料回包延時。
下載時,在訊息展示區顯示的通常只是一個很小的圖片,這時候只需要下載對應大小的縮圖即可,無需下載原圖。甚至,這裡可以將比縮圖更小的圖片二進位制資料直接放到訊息體中下發,並展示給使用者一個高斯模糊後的效果圖,在保證最低可用的情況下,減少使用者等待時間,提高使用者體驗。
語 音
對於不同的網路環境,採取不同質量的語音編碼演算法,在較好網路時,使用高質量語音,而在弱網環境下,則使用較低質量,優先保證可用性。
為了減少使用者等待時間,還可以採取邊錄邊傳的策略。由於錄音時間比較長,在錄製的過程中,我們就可以將錄好的部分先傳到伺服器,等到錄音完成,只需要上傳最後一個資料包,並告知伺服器錄音完成即可,基本上可以做到錄完即傳完,無需等待。
語音訊息沒有縮圖,因此語音下載基本就只能實打實的將原始檔案下載下來。
以上就是網易雲信對於Android 即時通訊開發的小結,歡迎各位積極提問,共同探討。