Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 506, comments - 13, trackbacks - 0, articles - 1

          本文編寫(xiě)時(shí)引用了“聊聊IM系統(tǒng)的即時(shí)性和可靠性”一文的部分內(nèi)容和圖片,感謝原作者。

          1、引言

          上一篇《零基礎(chǔ)IM開(kāi)發(fā)入門(二):什么是IM系統(tǒng)的實(shí)時(shí)性?》講到了IM系統(tǒng)的“立足”之本——“實(shí)時(shí)性”這個(gè)技術(shù)特征,本篇主要講解IM系統(tǒng)中的“可靠性”這個(gè)話題,內(nèi)容盡量做到只講原理不深入展開(kāi),避開(kāi)深層次的技術(shù)性探討,確保通俗易懂。


          閱讀對(duì)象:本系列文章主要閱讀對(duì)象為零IM基礎(chǔ)的開(kāi)發(fā)者或產(chǎn)品經(jīng)理,目標(biāo)是告訴你“IM系統(tǒng)是什么?”,盡量不深入探討具體的技術(shù)實(shí)現(xiàn),確保通俗易懂,老少皆宜。

          如您想從技術(shù)維度系統(tǒng)學(xué)習(xí)IM技術(shù)并著手自已的IM開(kāi)發(fā)(即解決“IM系統(tǒng)要怎么做?”這個(gè)疑問(wèn)),請(qǐng)從此文開(kāi)始:《新手入門一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM》。

          學(xué)習(xí)交流:

          - 即時(shí)通訊/推送技術(shù)開(kāi)發(fā)交流5群:215477170[推薦]

          - 移動(dòng)端IM開(kāi)發(fā)入門文章:《新手入門一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM

          - 開(kāi)源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK

          (本文同步發(fā)布于:http://www.52im.net/thread-3182-1-1.html

          2、系列文章

          零基礎(chǔ)IM開(kāi)發(fā)入門(一):什么是IM系統(tǒng)?

          零基礎(chǔ)IM開(kāi)發(fā)入門(二):什么是IM系統(tǒng)的實(shí)時(shí)性?

          零基礎(chǔ)IM開(kāi)發(fā)入門(三):什么是IM系統(tǒng)的可靠性?》(* 本文

          零基礎(chǔ)IM開(kāi)發(fā)入門(四):什么是IM系統(tǒng)的消息時(shí)序一致性?

          《零基礎(chǔ)IM開(kāi)發(fā)入門(五):什么是IM系統(tǒng)的安全性? (稍后發(fā)布)》

          《零基礎(chǔ)IM開(kāi)發(fā)入門(六):什么是IM系統(tǒng)的的心跳機(jī)制? (稍后發(fā)布)》

          《零基礎(chǔ)IM開(kāi)發(fā)入門(七):如何理解并實(shí)現(xiàn)IM系統(tǒng)消息未讀數(shù)? (稍后發(fā)布)》

          《零基礎(chǔ)IM開(kāi)發(fā)入門(八):如何理解并實(shí)現(xiàn)IM系統(tǒng)的多端消息漫游? (稍后發(fā)布)》

          3、正文概述

          一般來(lái)說(shuō),IM系統(tǒng)的消息“可靠性”,通常就是指聊天消息投遞的可靠性(準(zhǔn)確的說(shuō),這個(gè)“消息”是廣義的,因?yàn)檫€存用戶看不見(jiàn)的各種指令,為了通俗,統(tǒng)稱“消息”)。

          從用戶行為來(lái)講,消息“可靠性”應(yīng)該分為兩種類型:

          • 1)在線消息的可靠性:即發(fā)送消息時(shí),接收方當(dāng)前處于“在線”狀態(tài);
          • 2)離線消息的可靠性:即發(fā)送消息時(shí),接收方當(dāng)前處于“離線”狀態(tài)。

          從具體的技術(shù)表現(xiàn)來(lái)講,消息“可靠性”包含兩層含義:

          • 1)消息不丟:這很直白,發(fā)出去的消息不能像進(jìn)了黑洞一樣,一臉懵逼可不行;
          • 2)消息不重:這是丟消息的反面,消息重復(fù)了也不能容忍。

          對(duì)于“消息不丟”這個(gè)特征來(lái)說(shuō),細(xì)化下來(lái),它又包含兩重含義:

          • 1)已明確被對(duì)方收到;
          • 2)已明確未被對(duì)方收到。

          是的,對(duì)于第1)重含義好理解,第2)重含義的意思是:當(dāng)對(duì)方?jīng)]有成功收到時(shí),你的im系統(tǒng)也必須要感知到,否則,它同樣屬于被“丟”范疇。

          總之,一個(gè)成型的im系統(tǒng),必須包含這兩種消息“可靠性”邏輯,才能堪用,缺一不可。

          消息的可靠性(不丟失、不重復(fù))無(wú)疑是IM系統(tǒng)的重要指標(biāo),也是IM系統(tǒng)實(shí)現(xiàn)中的難點(diǎn)之一。本文以下文字,將從在線消息的可靠性和離線消息的可靠性進(jìn)行討論。

          4、典型的在線消息收發(fā)流程

          先看下面這張典型的im消息收發(fā)流程: 

          是的,這是一個(gè)典型的服務(wù)端中轉(zhuǎn)型IM架構(gòu)。

          所謂“服務(wù)端中轉(zhuǎn)型IM架構(gòu)”是指:一條消息從客戶端A發(fā)出后,需要先經(jīng)過(guò) IM 服務(wù)器來(lái)進(jìn)行中轉(zhuǎn),然后再由 IM 服務(wù)器推送給客戶端B,這種模式也是目前最常見(jiàn)的 IM 系統(tǒng)的消息分發(fā)架構(gòu)。

          你可能會(huì)說(shuō),IM不可以是P2P模式的嗎?是的,目前來(lái)說(shuō)主流IM基本都是服務(wù)器中轉(zhuǎn)這種方式,P2P模式在IM系統(tǒng)中用的很少。

          原因是以下兩個(gè)很明顯的弊端:

          • 1)P2P模式下,IM運(yùn)營(yíng)者很容易被用戶架空(無(wú)法監(jiān)管到用戶行為,用戶涉黃了怕不怕?);
          • 2)P2P模式下,群聊這種業(yè)務(wù)形態(tài),很難實(shí)現(xiàn)(我要在千人群中發(fā)消息給,不可能我自已來(lái)分發(fā)1000次吧)。

          話題有點(diǎn)跑偏,我們回到正題:在上面這張圖里,客戶A發(fā)送消息到服務(wù)端、服務(wù)端中轉(zhuǎn)消息給客戶B,假設(shè)這兩條數(shù)據(jù)鏈接中使用的通信協(xié)議是TCP,你認(rèn)為在TCP所謂可靠傳輸協(xié)議加持下,真的能保證IM聊天消息的可靠性嗎?

          答案是否定的。我們繼續(xù)看下節(jié)。

          5、TCP并不能保證在線消息的“可靠性”

          接上節(jié),在一個(gè)典型的服務(wù)端中轉(zhuǎn)型IM架構(gòu)中,即使使用“可靠的傳輸協(xié)議”TCP,也不能保證聊天消息的可靠性。為什么這么說(shuō)?

          要回答這個(gè)問(wèn)題,網(wǎng)上的很多文章,都會(huì)從服務(wù)端的角度舉例:比如消息發(fā)送時(shí)操作系統(tǒng)崩潰、網(wǎng)絡(luò)閃斷、存儲(chǔ)故障等等,總之很抽象,不太容易理解。

          這次我們從客戶端角度來(lái)理解,為什么使用了可靠傳輸協(xié)議TCP的情況下IM聊天消息仍然不可靠的問(wèn)題。

          具體來(lái)說(shuō):如何確保 IM 消息的可靠性是個(gè)相對(duì)復(fù)雜的話題,從客戶端發(fā)送數(shù)據(jù)到服務(wù)器,再?gòu)姆?wù)器送達(dá)目標(biāo)客戶端,最終在 UI 成功展示,其間涉及的環(huán)節(jié)很多,這里只取其中一環(huán)「接收端如何確保消息不丟失」來(lái)探討,粗略聊下我接觸過(guò)的兩種設(shè)計(jì)思路。

          說(shuō)到可靠送達(dá):第一反應(yīng)會(huì)聯(lián)想到 TCP 的可靠性。數(shù)據(jù)的可靠送達(dá)是個(gè)通用性的問(wèn)題,無(wú)論是網(wǎng)絡(luò)二進(jìn)制流數(shù)據(jù),還是上層的業(yè)務(wù)數(shù)據(jù),都有可靠性保障問(wèn)題,TCP 作為網(wǎng)絡(luò)基礎(chǔ)設(shè)施協(xié)議,其可靠性設(shè)計(jì)的可靠性是毋庸置疑的,我們就從 TCP 的可靠性說(shuō)起。

          在 TCP 這一層:所有 Sender 發(fā)送的數(shù)據(jù),每一個(gè) byte 都有標(biāo)號(hào)(Sequence Number),每個(gè) byte 在抵達(dá)接收端之后都會(huì)被接收端返回一個(gè)確認(rèn)信息(Ack Number), 二者關(guān)系為 Ack = Seq + 1。簡(jiǎn)單來(lái)說(shuō),如果 Sender 發(fā)送一個(gè) Seq = 1,長(zhǎng)度為 100 bytes 的包,那么 receiver 會(huì)返回一個(gè) Ack = 101 的包,如果 Sender 收到了這個(gè)Ack 包,說(shuō)明數(shù)據(jù)確實(shí)被 Receiver 收到了,否則 Sender 會(huì)采取某種策略重發(fā)上面的包。

          第一個(gè)問(wèn)題是:既然 TCP 本身是具備可靠性的,為什么還會(huì)出現(xiàn)消息接收端(Receiver)丟失消息的情況?

          看下圖一目了然:

          ▲ 上圖引用自《從客戶端的角度來(lái)談?wù)勔苿?dòng)端IM的消息可靠性和送達(dá)機(jī)制

          一句話總結(jié)上圖的含義:網(wǎng)絡(luò)層的可靠性不等同于業(yè)務(wù)層的可靠性。

          數(shù)據(jù)可靠抵達(dá)網(wǎng)絡(luò)層之后,還需要一層層往上移交處理,可能的處理有:

          • 1)安全性校驗(yàn);
          • 2)binary 解析;
          • 3)model 創(chuàng)建;
          • 4)寫(xiě) db;
          • 5)存入 cache;
          • 6)UI 展示;
          • 7)以及一些邊界問(wèn)題:比如斷網(wǎng)、用戶突然退出登陸、磁盤(pán)已滿、內(nèi)存溢出、app奔潰、突然關(guān)機(jī)等等。

          項(xiàng)目的功能特性越多,網(wǎng)絡(luò)層往上的處理出錯(cuò)的可能性就越大。

          舉個(gè)最簡(jiǎn)單的場(chǎng)景為例子:消息可靠抵達(dá)網(wǎng)絡(luò)層之后,寫(xiě) db 之前 IM APP 崩潰(不稀奇,是 App 都有崩潰的可能),雖然數(shù)據(jù)在網(wǎng)絡(luò)層可靠抵達(dá)了,但沒(méi)存進(jìn) db,下次用戶打開(kāi) App 消息自然就丟失了,如果不在業(yè)務(wù)層再增加可靠性保障(比如:后面要提到的網(wǎng)絡(luò)層面的消息重發(fā)保障),那么意味著這條消息對(duì)于接收端來(lái)說(shuō)就永遠(yuǎn)丟失了,也就自然不存在“可靠性”了。

          從客戶端角度理解IM的可能性以及解決辦法,可以詳細(xì)閱讀:從客戶端的角度來(lái)談?wù)勔苿?dòng)端IM的消息可靠性和送達(dá)機(jī)制》,本節(jié)引用的是該文中“4、TCP協(xié)議的可靠性之外還會(huì)出現(xiàn)消息丟失?”一節(jié)的文字。

          6、為在線消息增加“可靠性”保障

          那么怎樣在應(yīng)用層增加可靠性保障呢?

          有一個(gè)現(xiàn)成的機(jī)制可供我們借鑒:TCP協(xié)議的超時(shí)、重傳、確認(rèn)機(jī)制。

          具體來(lái)說(shuō)就是:

          • 1)在應(yīng)用層構(gòu)造一種ACK消息,當(dāng)接收方正確處理完消息后,向發(fā)送方發(fā)送ACK;
          • 2)假如發(fā)送方在超時(shí)時(shí)間內(nèi)沒(méi)有收到ACK,則認(rèn)為消息發(fā)送失敗,需要進(jìn)行重傳或其他處理。

          增加了確認(rèn)機(jī)制的消息收發(fā)過(guò)程如下: 

          我們可以把整個(gè)過(guò)程分為兩個(gè)階段。

          階段1:clientA -> server

          • 1-1:clientA向server發(fā)送消息(msg-Req);
          • 1-2:server收取消息,回復(fù)ACK(msg-Ack)給clientA;
          • 1-3:一旦clientA收到ACK即可認(rèn)為消息已成功投遞,第一階段結(jié)束。

          無(wú)論msg-A或ack-A丟失,clientA均無(wú)法在超時(shí)時(shí)間內(nèi)收到ACK,此時(shí)可以提示用戶發(fā)送失敗,手動(dòng)進(jìn)行重發(fā)。

          階段2:server -> clientB

          • 2-1:server向clientB發(fā)送消息(Notify-Req);
          • 2-2:clientB收取消息,回復(fù)ACK(Notify-ACk)給server;
          • 2-3:server收到ACK之后將該消息標(biāo)記為已發(fā)送,第二階段結(jié)束。

          無(wú)論msg-B或ack-B丟失,server均無(wú)法在超時(shí)時(shí)間內(nèi)收到ACK,此時(shí)需要重發(fā)msg-B,直到clientB返回ACK為止。

          關(guān)于IM聊天消息的可靠性保障問(wèn)的深入討論,可以詳讀:IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線實(shí)時(shí)消息的可靠投遞》,該文會(huì)深入討論這個(gè)話題。

          7、典型的離線消息收發(fā)流程

          說(shuō)完在線消息的“可靠性”問(wèn)題,我們?cè)摿私庖幌码x線消息了。

          7.1 離線消息的收發(fā)也存在“不可靠性”

          下圖是一張典型的IM離線消息流程圖:

          如上圖所示,和在線消息收發(fā)流程類似。

          離線消息收發(fā)流程也可劃分為兩個(gè)階段:

          階段1:clientA -> server

          • 1-1:clientA向server發(fā)送消息(msg-Req) ;
          • 1-2:server發(fā)現(xiàn)clientB離線,將消息存入offline-DB。

          階段2:server -> clientB

          • 2-1:clientB上線后向server拉取離線消息(pull-Req) ;
          • 2-2:server從offline-DB檢索相應(yīng)的離線消息推送給clientB(pull-res),并從offline-DB中刪除。

          顯然:離線消息收發(fā)過(guò)程同樣存在消息丟失的可能性。

          舉例來(lái)說(shuō):假設(shè)pull-res沒(méi)有成功送達(dá)clientB,而offline-DB中已刪除,這部分離線消息就徹底丟失了。

          7.2 離線消息的“可靠性”保障

          與在線消息收發(fā)流程類似,我們同樣需要在應(yīng)用層增加可靠性保障機(jī)制。

          下圖是增加了可靠性保障后的離線消息收發(fā)流程: 

          與初始的離線消息收發(fā)流程相比,上圖增加了1-3、2-4、2-5步驟:

          • 1-3:server將消息存入offline-DB后,回復(fù)ACK(msg-Ack)給clientA,clientA收到ACK即可認(rèn)為消息投遞成功;
          • 2-4:clientB收到推送的離線消息,回復(fù)ACK(res-Ack)給server;
          • 2-5:server收到res-ACk后確定離線消息已被clientB成功收取,此時(shí)才能從offline-DB中刪除。

          當(dāng)然,上述的保障機(jī)制,還存在性能優(yōu)化空間。

          當(dāng)離線消息的量較大時(shí):如果對(duì)每條消息都回復(fù)ACK,無(wú)疑會(huì)大大增加客戶端與服務(wù)器的通信次數(shù)。這種情況我們通常使用批量ACK的方式,對(duì)多條消息僅回復(fù)一個(gè)ACK。在某此后IM的實(shí)現(xiàn)中是將所有的離線消息按會(huì)話進(jìn)行分組,每組回復(fù)一個(gè)ACK,假如某個(gè)ACK丟失,則只需要重傳該會(huì)話的所有離線消息。

          有關(guān)離線消息的可靠性保障機(jī)制的詳細(xì)討論,可以詳讀:IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞》、《IM開(kāi)發(fā)干貨分享:如何優(yōu)雅的實(shí)現(xiàn)大量離線消息的可靠投遞》,這兩篇文章可以給你更深入具體的答案。

          8、聊天消息重復(fù)的問(wèn)題

          上面章節(jié)中,通過(guò)在應(yīng)用層加入重傳、確認(rèn)機(jī)制后,我們確實(shí)是杜絕了消息丟失的可能性。

          但由于重試機(jī)制的存在,我們會(huì)遇到一個(gè)新的問(wèn)題:那就是同一條消息可能被重復(fù)發(fā)送。

          舉一個(gè)最簡(jiǎn)單的例子:假設(shè)client成功收到了server推送的消息,但其后續(xù)發(fā)送的ACK丟失了,那么server將會(huì)在超時(shí)后再次推送該消息,如果業(yè)務(wù)層不對(duì)重復(fù)消息進(jìn)行處理,那么用戶就會(huì)看到兩條完全一樣的消息。

          消息去重的方式其實(shí)非常簡(jiǎn)單,一般是根據(jù)消息的唯一標(biāo)志(id)進(jìn)行過(guò)濾。

          具體過(guò)程在服務(wù)端和客戶端可能有所不同:

          • 1)客戶端 :我們可以通過(guò)構(gòu)造一個(gè)map來(lái)維護(hù)已接收消息的id,當(dāng)收到id重復(fù)的消息時(shí)直接丟棄;
          • 2)服務(wù)端 :收到消息時(shí)根據(jù)id去數(shù)據(jù)庫(kù)查詢,若庫(kù)中已存在則不進(jìn)行處理,但仍然需要向客戶端回復(fù)Ack(因?yàn)檫@條消息很可能來(lái)自用戶的手動(dòng)重發(fā))。

          關(guān)于消息的去重問(wèn)題,在一對(duì)一聊天的情況下,邏輯并不復(fù)雜,但在群聊模式下,會(huì)將問(wèn)題復(fù)雜化,有關(guān)群聊消息不丟和去重的詳細(xì)討論,可以深入閱讀:《IM群聊消息如此復(fù)雜,如何保證不丟不重?》。

          9、本文小結(jié)

          保證消息的可靠性是IM系統(tǒng)設(shè)計(jì)中很重要的一環(huán),能不能做到“消息不丟”、“消息不重”,對(duì)用戶的體驗(yàn)影響極大。

          所謂“可靠的傳輸協(xié)議”TCP也并不能保障消息在應(yīng)用層的可靠性。

          我們一般通過(guò)在應(yīng)用層的ACK應(yīng)答和重傳機(jī)制,來(lái)實(shí)現(xiàn)IM消息的可靠性保障。但由此帶來(lái)的消息重復(fù)問(wèn)題,需要我們額外進(jìn)行處理,最簡(jiǎn)單的方法就是通過(guò)消息ID進(jìn)行冪等去重。

          關(guān)于IM系統(tǒng)消息可靠性的理論基礎(chǔ),我們就探討到這里,有疑問(wèn)的讀者,可以在本文末尾留意,歡迎積極討論。

          10、參考資料

          [1] IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線實(shí)時(shí)消息的可靠投遞

          [2] IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞

          [3] IM開(kāi)發(fā)干貨分享:如何優(yōu)雅的實(shí)現(xiàn)大量離線消息的可靠投遞

          [4] 從客戶端的角度來(lái)談?wù)勔苿?dòng)端IM的消息可靠性和送達(dá)機(jī)制

          [5] 聊聊IM系統(tǒng)的即時(shí)性和可靠性

          [6] 學(xué)習(xí)筆記4——IM系統(tǒng)如何保證消息的可靠性

          [7] IM群聊消息如此復(fù)雜,如何保證不丟不重?

          附錄:更多IM開(kāi)發(fā)熱門技術(shù)點(diǎn)

          移動(dòng)端IM開(kāi)發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”

          移動(dòng)端IM開(kāi)發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)

          現(xiàn)代移動(dòng)端網(wǎng)絡(luò)短連接的優(yōu)化手段總結(jié):請(qǐng)求速度、弱網(wǎng)適應(yīng)、安全保障

          移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?

          移動(dòng)端IM開(kāi)發(fā)需要面對(duì)的技術(shù)問(wèn)題

          開(kāi)發(fā)IM是自己設(shè)計(jì)協(xié)議用字節(jié)流好還是字符流好?

          請(qǐng)問(wèn)有人知道語(yǔ)音留言聊天的主流實(shí)現(xiàn)方式嗎?

          如何保證IM實(shí)時(shí)消息的“時(shí)序性”與“一致性”?

          一個(gè)低成本確保IM消息時(shí)序的方法探討

          IM單聊和群聊中的在線狀態(tài)同步應(yīng)該用“推”還是“拉”?

          IM群聊消息如此復(fù)雜,如何保證不丟不重?

          談?wù)勔苿?dòng)端 IM 開(kāi)發(fā)中登錄請(qǐng)求的優(yōu)化

          移動(dòng)端IM登錄時(shí)拉取數(shù)據(jù)如何作到省流量?

          淺談移動(dòng)端IM的多點(diǎn)登錄和消息漫游原理

          完全自已開(kāi)發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?

          微信對(duì)網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)

          IM開(kāi)發(fā)基礎(chǔ)知識(shí)補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列

          微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)

          IM開(kāi)發(fā)基礎(chǔ)知識(shí)補(bǔ)課(六):數(shù)據(jù)庫(kù)用NoSQL還是SQL?讀這篇就夠了!

          IM里“附近的人”功能實(shí)現(xiàn)原理是什么?如何高效率地實(shí)現(xiàn)它?

          IM的掃碼登錄功能如何實(shí)現(xiàn)?一文搞懂主流應(yīng)用的掃碼登錄技術(shù)原理

          IM消息ID技術(shù)專題(一):微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)

          IM消息ID技術(shù)專題(二):微信的海量IM聊天消息序列號(hào)生成實(shí)踐(容災(zāi)方案篇)

          IM消息ID技術(shù)專題(三):解密融云IM產(chǎn)品的聊天消息ID生成策略

          IM消息ID技術(shù)專題(四):深度解密美團(tuán)的分布式ID生成算法

          IM消息ID技術(shù)專題(五):開(kāi)源分布式ID生成器UidGenerator的技術(shù)實(shí)現(xiàn)

          IM消息ID技術(shù)專題(六):深度解密滴滴的高性能ID生成器(Tinyid)

          IM開(kāi)發(fā)寶典:史上最全,微信各種功能參數(shù)和邏輯規(guī)則資料匯總

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

          ▲ 本文在公眾號(hào)上的鏈接是:點(diǎn)此進(jìn)入,原文鏈接是:http://www.52im.net/thread-3182-1-1.html



          作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時(shí)通訊開(kāi)發(fā)交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時(shí)是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處(也可前往 我的52im.net 找到我)。


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 邵东县| 桃园县| 镇康县| 六盘水市| 舟山市| 阿鲁科尔沁旗| 巴马| 衡东县| 海南省| 渭源县| 雷波县| 当涂县| 友谊县| 玉环县| 海丰县| 岚皋县| 木里| 雅安市| 开江县| 城固县| 东乌| 远安县| 宜阳县| 昌乐县| 滨海县| 保定市| 陕西省| 北碚区| 中西区| 尼玛县| 南城县| 扎兰屯市| 鄂尔多斯市| 景泰县| 长葛市| 肥乡县| 旺苍县| 喀什市| 获嘉县| 庆云县| 远安县|