日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

(转) Android平台上关于IM的实践总结

發布時間:2025/3/15 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (转) Android平台上关于IM的实践总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

IM通信在互聯網發展到現在已經是碼農的世界里人盡皆知的技術,特別在當下移動互聯網迅猛發展的時代這種技術的開發也更加火熱,其中老牌的代表作就有QQ和MSN,和最近新崛起的微信,默默,易信,來往等眼花繚亂的各種應用都把IM技術應用其中。我是Android開發人員,寫這篇文章主要原因也是因為我自己從事開發以來主要做過的幾款APP都是包含著IM通信,在不斷的摸爬滾打的解決問題的過程中,積累了一些經驗記錄便將其記錄到博客中作為自己一個階段性的總結,也可以分享其他需要的開發者,作為一種參考實踐的方案,當然,我也并非神馬大神級別的人物,如果博客中存在錯誤或者讀者看完后覺得有疑問,歡迎在文章下方留下你的建議或問題作為評論。

?

從socket到XMPP協議

一個簡單完成的IM通信流程如同下面的模型里面1-2-3-4的步驟所示,兩個移動設備之間的收發消息都需要服務器進行中轉并做消息的轉發。

整個IM流程中,服務器接收消息發送方的請求,并檢查接收方當前是否在線,如果在線的話則直接向接收方發送消息,如果不在線則作為離線消息存儲到數據庫中,等待接收方上線的時候再將消息進行發送。
IM作為一門網絡通信的技術,必然涉及到通信協議的問題,而在Android平臺上做IM開發,目前我所涉及到的協議有socket和XMPP兩種類型,當然,這兩者并不是一種并列的關系,從嚴格意義上來說socket是Java所有網絡實現通信的基石,在Java上所有任何網絡協議通信,最終都要依賴與socket來實現,在Android平臺上使用XMPP協議通信,其最終底層同樣還是依賴于socket實現,最典型的參考例子就是smack了,估計絕大多數小企業在做IM開發的時候,都會使用已經把XMPP協議封裝好smack,以此節省開發時間,smack本身就是用Java語言開發,并采用了mina作為核心實現的框架(mina本身就是一個Java的NIO通信框架,但是很久不更新了,原先mina的作者寫了一個新的NIO通信框架叫做netty,應該是做為mina的替代者)。作為socket和XMPP協議實現IM通信其主要的優缺點如下:


因此,在實際的IM開發中,到底是選用XMPP協議和使用socket來實現,可以根據開發應用場景和他們的優劣來決定,當然,也不僅僅局限于IM開發,服務器給客戶端做消息推送也可以作為參考。

?

長連接和數據丟包

IM開發中除了基本的消息收發,以及協議使用方式的選擇外,還需要解決所有IM通信技術所面臨的兩個共性問題。
其一,保持客戶端和服務器間的長連接。這是由于業務場景所需要, IM通信實現的基礎是需要時時刻刻保持客戶端在服務器上的在線狀態,這樣才能保證發送方的消息能夠及時到接收方,特別是微信的設計概念出來后,IM類型的客戶端已經沒有在線和離線狀態的區別了,這是和QQ最大的區別 ,在這種情況下對客戶端實時在線的要求就變得更高。那么作為客戶端如何實時保持在線狀態呢?由于Java網絡通信的最底層都要依賴于socket來實現,而socket又分為UDP和TCP兩種類型,從理論上來講,我們使用TCP類型的socket來做實現通信即可保證長連接的實現,不過這僅僅是理論上而已,為什么單靠TCP不行咧,這跟我們真是的網絡環境和操作系統都有一定的關系,預知為毛,請接著往下看。
首先,在上一面那種簡單的IM通信圖中,僅僅列出了IM通信的服務器和客戶端,但是在實際的網絡環境是非常復雜的(如下圖所示,黃色的閃電圖形代表一個連接),我們發送的消息報文是需要經過很多不同的運營商線路,在各個交換機和路由器間穿梭才能最終到達接收方的設備上,下圖是一個簡單的網絡消息傳遞圖,黃色的閃電線連起來就是TCP所保持的長連接,理論上這個鏈接是一直保持通暢的,所以客戶端只需建立連接后就可以撒手不管。

?

但是從性能和耗費資源的角度來看,使用socket是非常耗費資源的,特別是保持長連接的TCP類型socket,所以在實際的運營商設備上,這個長連接保持一小段時間后就會被斷開,這樣做也是運營商為了節省和充分利用設備的資源,而中間有一環的鏈接斷開之后,雙方就再也無法保持長連接且進行通信,因為如果僅僅依賴于TCP的長連接,此時服務器和客戶端是并不知道鏈接已經被斷開的,所以就會造成下面將要說到的數據丟包問題。除了運營商自己會將設備的長連接斷開外,還有包括其他原因也將導致鏈接斷開,例如,運營商的設別斷電或故障等、移動設別接收端本身設備斷點掉線等諸多復雜的因素存在導致直接依賴于TCP的長連接方案不可行,其次例如Android操作系統本身也是會對TCP的長連接做處理,諸如之前所說的,TCP的socket長連接是非常耗費資源的,這種資源相對于移動設備來說更加寶貴,所以在一定時間的TCP長連接閑置后,系統也會自動清除設備上的長連接,以此節省移動設別上的能耗。為了徹底解決長連接的問題,IM技術實際上引入了心跳包的方案,說起來這種實現方案也并不復雜,就是客戶端每個一會兒就要向服務器發送一個請求報文(這個報文可以是空的,跟服務器那邊約定好),目的是為了告訴服務器“我是在線的”,而服務器在接收心跳請求報文之后同樣需要反饋一個消息告訴客戶端“我知道了”,通過應用層上的不斷進行消息收發來維持長連接的存在,當客戶端沒有一直沒有收到服務器的反饋時默認已經掉線,進行相關的業務邏輯處理后將再重連服務器,同樣服務器沒有收到客戶端發送來的心跳包時,可以默認客戶端已經掉線,將服務器上的通信socket進行關閉回收資源。
其二,客戶端發送數據的丟包問題,在第一個原因中降到運營商和各種各樣的網絡情況都會導致發送數據的丟包,陷入以下的這種場景A和B之間同樣經歷1-2-3-4的一個消息收發流程,但是不幸的是由于各種原因,B返回的消息在IM服務器轉發給A的時候丟失了,此時A并不知道B回復了他消息,而服務器也不知道A沒有收到B的回復,這種情況下所帶給用戶的體驗是及其差勁的。

那么要如何應對這種丟包問題呢?目前想到的一種簡單粗暴的可行方案就服務器每次向客戶端發送一條消息都要為這條消息做一個id的標記,客戶端收到此消息后需要返回一個回執給服務器,作為標記當前客戶端已經收到消息的證明,如果服務器發送出消息而遲遲沒有收到服務器的回執,就把這些消息作為離線消息存放到數據庫中,等到客戶端重現上線的時候再將離線消息推送給客戶端。通過這種方式就可以很好的解決了消息包發送途中丟包而客戶端和服務器都不知情的問題。體驗一下子就彪上去了,咔咔咔。

?

優化性能

由于IM通信的實時要求性比較高,伴隨著長連接所耗費的資源也相對比較多,所以在移動平臺上的IM通信客戶端想要性能和體驗上得去,性能優化是必不可少的,對此為Android平臺上IM優化做一些小小的總結,當然不一定很全面,如果你有更好的建議歡迎在評論里面做補充哈。

?

?

小結

以上的內容僅僅時平時開發過程中積累的一部分知識和經驗的總結,希望他能幫助到其他在尋找資料開發者,同時,也感謝很多開源項目的貢獻者以及熱愛分享的博客撰寫者,因為有他們的貢獻和分享才有這篇文章的誕生,才有我在開發過程中的進步。本文的word文檔也會同步到我的github倉庫上,歡迎拍磚,歡迎轉載,但請注明出處,請勿隨意用于商業用途

總結

以上是生活随笔為你收集整理的(转) Android平台上关于IM的实践总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。