Android开发需要了解的 IM 知识
引言
即便在通訊如此發(fā)達的今天,IM 也依然是諸多場景下非常重要的基礎(chǔ)能力。因此做為 一名 Android 開發(fā),不可避免的會遇到一些IM 相關(guān)的需求或問題。本文以一個Android開發(fā)的角度來講述IM 開發(fā)相關(guān)的基礎(chǔ)知識。
想要技術(shù)干貨、行業(yè)洞察,歡迎關(guān)注網(wǎng)易云信博客。
了解網(wǎng)易云信,來自網(wǎng)易核心架構(gòu)的通信與視頻云服務(wù)。
IM開發(fā)需要面對的問題
網(wǎng)絡(luò)問題
TCP 的三次握手建立連接是一個非常耗時的過程。在 IM 場景下,數(shù)據(jù)的傳輸將會非常的頻繁,如果每次傳輸都建立一個 TCP 連接,那么這個效率是不能接受的,并且頻繁的建立連接可能會發(fā)生socket錯誤,所以我們需要 “復(fù)用”TCP連接,也就是平時所說的TCP長連接。
TCP 長連接
短連接在建立后,當數(shù)據(jù)傳輸完畢時會立即關(guān)閉,下次需要傳輸數(shù)據(jù)時需要重新建立連接,在日常的業(yè)務(wù)場景非常常見,比如通過 http/https 請求獲取Server 數(shù)據(jù)。而長連接在傳輸完數(shù)據(jù)后并不會關(guān)閉,這樣下次需要傳輸數(shù)據(jù)時就可以直接使用已經(jīng)建立好的連接,這中間省去了連接建立的時間。但是建立一個 TCP 長連接卻并不是“建立后不關(guān)閉”那么簡單,因為 TCP 長連接會“被動”關(guān)閉。
網(wǎng)絡(luò)地址轉(zhuǎn)換 (NAT)
IPv4的容量是有限的,隨著接入Internet的計算機數(shù)量的不斷猛增,IP地址資源也就愈加顯得捉襟見肘,于是也就產(chǎn)生了 NAT技術(shù)。簡單來說,NAT就是在局域網(wǎng)內(nèi)部網(wǎng)絡(luò)中使用內(nèi)部地址,而當內(nèi)部節(jié)點要與外部網(wǎng)絡(luò)進行通訊時,就在網(wǎng)關(guān)(可以理解為出口,打個比方就像院子的門一樣)處,將內(nèi)部地址替換成公用地址,從而在外部公網(wǎng)(Internet)上正常使用,NAT可以使多臺計算機共享Internet連接,這一功能很好地解決了公共 IP地址緊缺的問題。通過這種方法,可以只申請一個合法IP地址,就把整個局域網(wǎng)中的計算機接入Internet中。
而我們就處于運營商(移動/聯(lián)通/電信。。。)的局域網(wǎng)內(nèi)。當我們接入運營商的網(wǎng)絡(luò)后,會分配到一個運營商的內(nèi)部 IP地址,于是我們就可以使用這個IP地址建立連接向外傳輸數(shù)據(jù)了。但是當這個IP閑置了一段時間(NAT超時時間)后,運營商為了節(jié)約資源,會把分配給我們IP回收掉。此時如果我們還繼續(xù)使用之前那個未關(guān)閉的連接去傳輸數(shù)據(jù),那么毫無疑問會失敗的。下面是一些運營商的 NAT超時時間。
網(wǎng)絡(luò)NAT超時時間中國移動3G/2G5 min中國聯(lián)通2G5 min中國電信3G大于 28 min
要想長連接一直有效,那么閑置時間就不能太長,所以在閑置時我們需要向外(Server)傳輸一些數(shù)據(jù)包,這也就是常說的“心跳包”,用于告訴運營商這個 IP 還在被使用,告訴Server 客戶端還在線。
心跳策略
心跳策略一般分為兩種:
1. 固定心跳
2. 動態(tài)心跳
這里講一下固定心跳,動態(tài)心跳可以參考 微信心跳 。固定心跳其實就是間隔固定時間發(fā)送一個心跳包。
心跳間隔 X 的值需要參考運營商的 NAT 超時時間確定,不能大于最小的 NAT超時時間,也不能太小,要不Server 的負擔非常重。一般取一個比較接近最小的NAT超時時間,比如4分鐘。
協(xié)議問題
協(xié)議決定是消息以什么樣的形式傳輸,即發(fā)送時如果對消息進行封裝,接收時如何解析。比如可以將消息體以 XML 的形式進行處理,這也就是 XMPP 協(xié)議,參考下面一個消息示意:
隔壁老王:你兒子長的比你帥多了。
老李:嘿嘿,謝謝夸獎!
<message> ??? <from>隔壁老王</from> ??? <to>老李</to> ??? <context>你兒子長的比你帥多了。</context> ??? <type>text</type> </message> <message> ??? <from>老李</from> ??? <to>隔壁老王</to> ??? <context>嘿嘿,謝謝夸獎!</context> ??? <type>text</type> </message>從上面的消息示意,我們可以發(fā)現(xiàn)一條消息的內(nèi)容可以拆分成很多屬性,而協(xié)議就是把這些屬性組合起來。
以 XML 的形式傳輸消息,最大的一個問題,就是冗余數(shù)據(jù)太多了,特別是當消息的屬性比較多時。
那么有沒什么格式能盡可能有減小冗余數(shù)據(jù)?
其實無論消息如何封裝,最終傳輸?shù)目隙ㄊ嵌M制流,那么完全可以直接用二進制的形式對消息進行封裝,這也就是二進制協(xié)議。下面是一個簡單二進制協(xié)議的實現(xiàn)示意。
一條消息由from + to + context + type這幾個屬性組成,那么我們完全可以按順序存儲在二進制中,由于內(nèi)容長度不確定,所以每個屬性的開頭我們可以使用固定字節(jié)數(shù)來記錄這個屬性的內(nèi)容長度。當然,這里只是展示了一個二進制協(xié)議的例子,實際的消息會比這復(fù)雜多了,但是核心思路就是這么簡單,最終無非是設(shè)計與實現(xiàn)形式上的差距。
及時性問題
IM的作為即時通訊,如果無法保證消息及時觸達,那么意義就大打折扣。要保證消息及時觸達,最關(guān)鍵要做到以下兩點:
1. App 進程要盡量存活,也就是進程保活 ;
2. 在 App進程掛掉后,能夠喚醒起來;
進程保活
進程保活其實是屬于 Android 平臺的一個話題,相信大家日常開發(fā)也遇到過,細節(jié)就不在這長篇大論了,簡單的說下幾個原則:
1. 優(yōu)化內(nèi)存,減小內(nèi)存的占用,會大大的減小被 kill 的機率;
2. 多進程,將 UI 進程與 IM 進程獨立出來,這樣 IM 的進程負擔就會小很多;
進程喚醒
嚴格意義上來說進程喚醒是屬于進程保活的一個分支,這里單獨列出來,是因為進程喚醒關(guān)注的是進程掛掉之后的動作。對于進程喚醒,這里也只列些原則,詳細的可以去查閱相關(guān)資料。
1. 靜態(tài)注冊監(jiān)聽廣播(<7.0)
2. Alarm定時任務(wù),定時去檢查進程是否存活。
3. JobScheduler定時任務(wù),定時去檢查進程是否存活( >5.0 )
4. 接入廠商推送
網(wǎng)易云信(NeteaseYunXin)是集網(wǎng)易18年IM以及音視頻技術(shù)打造的PaaS服務(wù)產(chǎn)品,來自網(wǎng)易核心技術(shù)架構(gòu)的通信與視頻云服務(wù),穩(wěn)定易用且功能全面,致力于提供全球領(lǐng)先的技術(shù)能力和場景化解決方案。開發(fā)者通過集成客戶端SDK和云端OPEN API,即可快速實現(xiàn)包含IM、音視頻通話、直播、點播、互動白板、短信等功能。
?
總結(jié)
以上是生活随笔為你收集整理的Android开发需要了解的 IM 知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这个一夜暴富的秘诀你还不知道?
- 下一篇: Android Camera的进化史