Android開發需要了解的 IM 知識

引言
即便在通訊如此發達的今天,IM 也依然是諸多場景下非常重要的基礎能力。因此做爲 一名 Android 開發,不可避免的會遇到一些IM 相關的需求或問題。本文以一個Android開發的角度來講述IM 開發相關的基礎知識。

想要閱讀更多技術乾貨、行業洞察,歡迎關注網易雲信博客。
瞭解網易雲信,來自網易核心架構的通信與視頻雲服務。
IM開發需要面對的問題
網絡問題,如何高效快速的傳輸數據?
協議問題,消息如何封裝?
及時性問題,如何進行進程保活?
網絡問題
  TCP 的三次握手建立連接是一個非常耗時的過程。在 IM 場景下,數據的傳輸將會非常的頻繁,如果每次傳輸都建立一個 TCP 連接,那麼這個效率是不能接受的,並且頻繁的建立連接可能會發生socket錯誤,所以我們需要 “複用”TCP連接,也就是平時所說的TCP長連接。
TCP 長連接
短連接在建立後,當數據傳輸完畢時會立即關閉,下次需要傳輸數據時需要重新建立連接,在日常的業務場景非常常見,比如通過 http/https 請求獲取Server 數據。而長連接在傳輸完數據後並不會關閉,這樣下次需要傳輸數據時就可以直接使用已經建立好的連接,這中間省去了連接建立的時間。但是建立一個 TCP 長連接卻並不是“建立後不關閉”那麼簡單,因爲 TCP 長連接會“被動”關閉。
網絡地址轉換 (NAT)
   IPv4的容量是有限的,隨着接入Internet的計算機數量的不斷猛增,IP地址資源也就愈加顯得捉襟見肘,於是也就產生了 NAT技術。簡單來說,NAT就是在局域網內部網絡中使用內部地址,而當內部節點要與外部網絡進行通訊時,就在網關(可以理解爲出口,打個比方就像院子的門一樣)處,將內部地址替換成公用地址,從而在外部公網(Internet)上正常使用,NAT可以使多臺計算機共享Internet連接,這一功能很好地解決了公共 IP地址緊缺的問題。通過這種方法,可以只申請一個合法IP地址,就把整個局域網中的計算機接入Internet中。

  而我們就處於運營商(移動/聯通/電信。。。)的局域網內。當我們接入運營商的網絡後,會分配到一個運營商的內部 IP地址,於是我們就可以使用這個IP地址建立連接向外傳輸數據了。但是當這個IP閒置了一段時間(NAT超時時間)後,運營商爲了節約資源,會把分配給我們IP回收掉。此時如果我們還繼續使用之前那個未關閉的連接去傳輸數據,那麼毫無疑問會失敗的。下面是一些運營商的 NAT超時時間。
網絡NAT超時時間中國移動3G/2G5 min中國聯通2G5 min中國電信3G大於 28 min
   要想長連接一直有效,那麼閒置時間就不能太長,所以在閒置時我們需要向外(Server)傳輸一些數據包,這也就是常說的“心跳包”,用於告訴運營商這個 IP 還在被使用,告訴Server 客戶端還在線。
心跳策略
  心跳策略一般分爲兩種:
    1. 固定心跳
    2. 動態心跳
這裏講一下固定心跳,動態心跳可以參考 微信心跳 。固定心跳其實就是間隔固定時間發送一個心跳包。

心跳間隔 X 的值需要參考運營商的 NAT 超時時間確定,不能大於最小的 NAT超時時間,也不能太小,要不Server 的負擔非常重。一般取一個比較接近最小的NAT超時時間,比如4分鐘。
協議問題
   協議決定是消息以什麼樣的形式傳輸,即發送時如果對消息進行封裝,接收時如何解析。比如可以將消息體以 XML 的形式進行處理,這也就是 XMPP 協議,參考下面一個消息示意:
隔壁老王:你兒子長的比你帥多了。
老李:嘿嘿,謝謝誇獎!
<message>

<from>隔壁老王</from>
<to>老李</to>
<context>你兒子長的比你帥多了。</context>
<type>text</type>

</message>

<message>

<from>老李</from>
<to>隔壁老王</to>
<context>嘿嘿,謝謝誇獎!</context>
<type>text</type>

</message>
  從上面的消息示意,我們可以發現一條消息的內容可以拆分成很多屬性,而協議就是把這些屬性組合起來。
以 XML 的形式傳輸消息,最大的一個問題,就是冗餘數據太多了,特別是當消息的屬性比較多時。
  那麼有沒什麼格式能儘可能有減小冗餘數據?
  其實無論消息如何封裝,最終傳輸的肯定是二進制流,那麼完全可以直接用二進制的形式對消息進行封裝,這也就是二進制協議。下面是一個簡單二進制協議的實現示意。

  一條消息由from + to + context + type這幾個屬性組成,那麼我們完全可以按順序存儲在二進制中,由於內容長度不確定,所以每個屬性的開頭我們可以使用固定字節數來記錄這個屬性的內容長度。當然,這裏只是展示了一個二進制協議的例子,實際的消息會比這複雜多了,但是核心思路就是這麼簡單,最終無非是設計與實現形式上的差距。
及時性問題
  IM的作爲即時通訊,如果無法保證消息及時觸達,那麼意義就大打折扣。要保證消息及時觸達,最關鍵要做到以下兩點:
   1. App 進程要儘量存活,也就是進程保活 ;
   2. 在 App進程掛掉後,能夠喚醒起來;
進程保活
  進程保活其實是屬於 Android 平臺的一個話題,相信大家日常開發也遇到過,細節就不在這長篇大論了,簡單的說下幾個原則:
   1. 優化內存,減小內存的佔用,會大大的減小被 kill 的機率;
   2. 多進程,將 UI 進程與 IM 進程獨立出來,這樣 IM 的進程負擔就會小很多;
進程喚醒
  嚴格意義上來說進程喚醒是屬於進程保活的一個分支,這裏單獨列出來,是因爲進程喚醒關注的是進程掛掉之後的動作。對於進程喚醒,這裏也只列些原則,詳細的可以去查閱相關資料。
   1. 靜態註冊監聽廣播(<7.0)
   2. Alarm定時任務,定時去檢查進程是否存活。
   3. JobScheduler定時任務,定時去檢查進程是否存活( >5.0 )
   4. 接入廠商推送
網易雲信(NeteaseYunXin)是集網易18年IM以及音視頻技術打造的PaaS服務產品,來自網易核心技術架構的通信與視頻雲服務,穩定易用且功能全面,致力於提供全球領先的技術能力和場景化解決方案。開發者通過集成客戶端SDK和雲端OPEN API,即可快速實現包含IM、音視頻通話、直播、點播、互動白板、短信等功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章