彭 飛
(安徽信息工程學(xué)院計(jì)算機(jī)與軟件工程學(xué)院,安徽 蕪湖241000)
國(guó)內(nèi)軟件開(kāi)發(fā)和服務(wù)型企業(yè),都在嘗試和提供消息推送服務(wù).但是,對(duì)于專(zhuān)門(mén)從事軟件開(kāi)發(fā)的企業(yè)來(lái)說(shuō),掌握一個(gè)比較完整和合理的基于安卓原生框架的消息推送系統(tǒng)的設(shè)計(jì)原理,意義之重大不言而喻.可以在這個(gè)實(shí)現(xiàn)的基礎(chǔ)之上,根據(jù)自身業(yè)務(wù)的需求,只要做與業(yè)務(wù)相關(guān)的部分,不再需要重復(fù)去設(shè)計(jì)底層功能.這樣就簡(jiǎn)化了對(duì)設(shè)計(jì)的要求,同時(shí),也對(duì)開(kāi)發(fā)人員的能力要求方面有所降低.開(kāi)發(fā)人員只是業(yè)務(wù)方面的行家,只要關(guān)注與自己業(yè)務(wù)相關(guān)的開(kāi)發(fā),努力把業(yè)務(wù)做到極致,把用戶(hù)體驗(yàn)做到更加豐富多彩.對(duì)于底層、協(xié)議等這些比較晦澀、難懂的技術(shù)實(shí)現(xiàn)不需要關(guān)注.
XMPP[1]:中文意思是擴(kuò)展消息出席協(xié)議.設(shè)計(jì)的目的是使用相對(duì)較小的結(jié)構(gòu)化數(shù)據(jù)(稱(chēng)為“XML節(jié)”) 片段在網(wǎng)絡(luò)完成上任何兩個(gè)(或更多)實(shí)體之間的數(shù)據(jù)交換.典型的應(yīng)用場(chǎng)景是分布式客戶(hù)機(jī)-服務(wù)器體系結(jié)構(gòu),一個(gè)客戶(hù)端需要連接到服務(wù)器才能與其他實(shí)體(或與其他某個(gè)服務(wù)器)交換XML節(jié).
兩個(gè)實(shí)體之間交換信息大體需要經(jīng)歷下面的過(guò)程.
(1)設(shè)置IP地址和需要連接到端口號(hào),基于全域名解析;
(2)打開(kāi)TCP(Transmission Control Protocol)連接;
(3)在TCP上打開(kāi)XML流;
(4)協(xié)商TLS(Transport Layer Security)通道加密;
(5)使用SASL(Simple Authentication and Security Layer)機(jī)制驗(yàn)證身份;
(6)綁定資源流;
(7)通過(guò)網(wǎng)絡(luò)與其他節(jié)點(diǎn)交換XML數(shù)據(jù)節(jié);
(8)關(guān)閉 XML 流;
(9)關(guān)閉TCP 連接.
XMPP協(xié)議的網(wǎng)絡(luò)應(yīng)用通常被實(shí)現(xiàn)成基于分布式的客戶(hù)端-服務(wù)器網(wǎng)絡(luò)架構(gòu)模型,實(shí)體之間采用TCP連接,并且每個(gè)客戶(hù)端只能夠與特定的服務(wù)器連接,要想實(shí)現(xiàn)端對(duì)端的連接,則中間必須經(jīng)過(guò)一個(gè)或多個(gè)服務(wù)器的轉(zhuǎn)發(fā)[2].所以,在基于XMPP 協(xié)議的通信鏈路中,根據(jù)扮演的角色來(lái)細(xì)分的話(huà),整個(gè)通訊的結(jié)構(gòu)可以劃分成四大組件.
服務(wù)器:主要的功能是用來(lái)接收、轉(zhuǎn)發(fā)或處理傳輸數(shù)據(jù),不同的實(shí)體在服務(wù)器上都有一個(gè)唯一的標(biāo)識(shí),便于服務(wù)器來(lái)區(qū)分.服務(wù)器也扮演數(shù)據(jù)存儲(chǔ)和管理客戶(hù)端的功能,能夠根據(jù)業(yè)務(wù)的需要實(shí)現(xiàn)功能定制和擴(kuò)展.
客戶(hù)端:信息傳遞的發(fā)起者,數(shù)據(jù)的傳遞必須通過(guò)服務(wù)器的轉(zhuǎn)發(fā)才能到達(dá)其他服務(wù)器、客戶(hù)端.每個(gè)客戶(hù)端必須有明確的唯一的標(biāo)識(shí)符,同時(shí)客戶(hù)端必須完全支持TCP套接字(Socket),能夠理解XML信息流的數(shù)據(jù)類(lèi)型和正確解析XML數(shù)據(jù).
網(wǎng)關(guān):主要的功能是連接異構(gòu)系統(tǒng),實(shí)現(xiàn)互相通信,目的是實(shí)現(xiàn)不同協(xié)議之間的轉(zhuǎn)換,起到一個(gè)協(xié)議信息轉(zhuǎn)換的作用.
網(wǎng)絡(luò):是實(shí)現(xiàn)不同實(shí)體之間互聯(lián)互通的通訊連接和信息傳輸?shù)奈锢磔d體.
支持XMPP協(xié)議網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)如圖1所示.

圖1 網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)
XMPP地址格式和我們經(jīng)常使用的電子郵件類(lèi)似,使用全局唯一地址來(lái)標(biāo)識(shí)XMPP的實(shí)體,利用域名系統(tǒng)在網(wǎng)絡(luò)上轉(zhuǎn)發(fā)和傳遞消息.XMPP協(xié)議規(guī)范中明確規(guī)定,所有實(shí)體都是可尋址的,不光是特別的客戶(hù)端和服務(wù)器,而且提供附加服務(wù)的服務(wù)器都能被其他客戶(hù)端和服務(wù)器訪問(wèn).XMPP服務(wù)器地址類(lèi)似“網(wǎng)絡(luò)域名”形式,比如xm.mydomain.com,而注冊(cè)在該服務(wù)器上賬戶(hù)地址形式mars@xm.mydomain.com,服務(wù)器設(shè)備或資源形式是mars@ xm.mydomain.com / balcon.XMPP出身Jabber,所以其地址被稱(chēng)為Jabber Id.所以,一個(gè)JID的信息是由實(shí)體名稱(chēng)、路由服務(wù)器和資源三部分組成[3].
消息推送的主要功能是向安卓手機(jī)客戶(hù)端推送文本消息,底層的通訊協(xié)議使用XMPP協(xié)議,要實(shí)現(xiàn)這個(gè)功能,需要服務(wù)器端的支持.
服務(wù)器端需支持以下功能:
(1)能夠完成安卓客戶(hù)端的注冊(cè)、連接和登錄常用的功能.新的客戶(hù)端第一次連接到服務(wù)器時(shí),服務(wù)器獲取客戶(hù)端的信息并把信息寫(xiě)入后臺(tái)的數(shù)據(jù)庫(kù).
(2)服務(wù)器一直監(jiān)聽(tīng)客戶(hù)端狀態(tài)的變化(離線或在線),一旦客戶(hù)端離線或在線,自動(dòng)更新記錄在數(shù)據(jù)庫(kù)表中的客戶(hù)端的狀態(tài),便于管理員隨時(shí)通過(guò)管理頁(yè)面查看當(dāng)前在線用戶(hù)的詳細(xì)信息.
(3)服務(wù)端以管理員控制臺(tái)的方式提供輸入文本信息界面,輸入需要推送的信息之后,能夠把該條信息主動(dòng)向安卓手機(jī)客戶(hù)端推送.推送形式目前分為向指定的用戶(hù)推送與向系統(tǒng)數(shù)據(jù)庫(kù)中所有用戶(hù)推送這兩種形式.
安卓客戶(hù)端需支持以下功能:
(1)App部署成功,打開(kāi)消息推送功能,自動(dòng)連接到指定的服務(wù)器完成新用戶(hù)注冊(cè)功能.注冊(cè)的信息寫(xiě)入到手機(jī)中配置信息中,已經(jīng)在服務(wù)器完成過(guò)注冊(cè)之后,直接使用保存的注冊(cè)信息登錄.
(2)客戶(hù)端提供心跳機(jī)制,定時(shí)向服務(wù)器發(fā)送連接來(lái)維護(hù)自己與與服務(wù)器的連接.
(3)安卓客戶(hù)端屬于移動(dòng)設(shè)備,有可能使用WIFI接入,一旦離開(kāi)WIFI的覆蓋區(qū)域,自動(dòng)向服務(wù)器發(fā)送連接斷開(kāi)的請(qǐng)求,當(dāng)再次進(jìn)入覆蓋區(qū)域,具有斷線重連的功能.
要實(shí)現(xiàn)上面定義的業(yè)務(wù)功能,需要從下面幾個(gè)方面來(lái)思考:
(1)一個(gè)安卓客戶(hù)端和服務(wù)器的通訊過(guò)程可以簡(jiǎn)化為一對(duì)一模型,通訊的過(guò)程是建立連接、傳遞數(shù)據(jù)和關(guān)閉連接.只不過(guò),要使用XMPP協(xié)議的兩個(gè)互相通訊的實(shí)體之間,傳遞的是XML數(shù)據(jù)流.Java語(yǔ)言提供的網(wǎng)絡(luò)API很容易實(shí)現(xiàn)基于Socket的通訊網(wǎng)絡(luò).
(2)如果涉及到多個(gè)安卓客戶(hù)端,那么通訊模型變成了一對(duì)多,服務(wù)器就需要維護(hù)連接列表來(lái)存放和處理每一個(gè)客戶(hù)端數(shù)據(jù).
(3)XML的消息流到達(dá)安卓客戶(hù)端,需要被解析并以文本的形式展示,服務(wù)端的數(shù)據(jù)何時(shí)到達(dá)具有不確定性,所以,需要使用偵聽(tīng)機(jī)制來(lái)異步處理消息,Android提供的APIs已經(jīng)能夠滿(mǎn)足這個(gè)功能.服務(wù)器如果向在線的安卓客戶(hù)端發(fā)送一條信息,只需要遍歷連接列表,使用Socket發(fā)送一段XML流即可.
通過(guò)上面的思考和分析,消息推送的底層通訊的本質(zhì)是Java語(yǔ)言的Socket網(wǎng)絡(luò)通訊,通過(guò)Socket建立的管道流中傳輸?shù)氖荴ML數(shù)據(jù),這些數(shù)據(jù)是按照XMPP協(xié)議規(guī)范構(gòu)造的,服務(wù)器和安卓客戶(hù)端必須能夠理解這些XML數(shù)據(jù).所以,消息推送需要設(shè)計(jì)的基礎(chǔ)類(lèi)庫(kù)必須要能實(shí)現(xiàn)下面的要求.
(1)附加在Socket通訊之上的應(yīng)用必須要提供對(duì)Socket通訊的封裝,提供性能優(yōu)良的多客戶(hù)端連接處理.
(2)需要設(shè)計(jì)一系列的類(lèi)來(lái)抽象服務(wù)器和安卓客戶(hù)端的連接、客戶(hù)端會(huì)話(huà)以及對(duì)連接的處理.
(3)需要設(shè)計(jì)XML數(shù)據(jù)流的解析器,提供對(duì)XML到應(yīng)用層數(shù)據(jù)解析工作,同時(shí),基于XMPP通訊所需要的格式化XML數(shù)據(jù)構(gòu)造器,完成應(yīng)用層數(shù)據(jù)到XML的解析.
(4)消息接收和處理的時(shí)機(jī)具有不確定性,需要設(shè)計(jì)一系列的監(jiān)聽(tīng)器來(lái)監(jiān)聽(tīng)連接狀態(tài)的變化,進(jìn)而觸發(fā)一系列事件.
消息推送暫時(shí)只支持向在線的安卓客戶(hù)端推送文本消息.服務(wù)端需要完成的工作分成二塊,第一塊是在某個(gè)端口上監(jiān)聽(tīng)安卓客戶(hù)端套接字連接,連接一旦建立,安卓客戶(hù)端需要使用長(zhǎng)連接的方式主動(dòng)和服務(wù)器保持連接,處理來(lái)自服務(wù)器的不同類(lèi)型的消息.第二塊是作為Web應(yīng)用服務(wù)器,在80端口監(jiān)聽(tīng)PC客戶(hù)端瀏覽器的HTTP頁(yè)面請(qǐng)求,管理員使用瀏覽器在遠(yuǎn)程呼出管理界面,實(shí)現(xiàn)對(duì)安卓客戶(hù)端的管理和文本消息的推送.服務(wù)器能夠響應(yīng)瀏覽器的URL請(qǐng)求,調(diào)用部署在服務(wù)器上與URL請(qǐng)求一一對(duì)應(yīng)的服務(wù)組件來(lái)處理請(qǐng)求,最后生成響應(yīng),呈現(xiàn)處理結(jié)果給客戶(hù)端.
XMPP服務(wù)模塊可以實(shí)現(xiàn)成一個(gè)獨(dú)立的服務(wù)器,HTTP服務(wù)模塊也是一個(gè)獨(dú)立的應(yīng)用服務(wù)器,兩個(gè)服務(wù)模塊局部數(shù)據(jù)是共享的.所以,系統(tǒng)結(jié)構(gòu)設(shè)計(jì)可以用圖2來(lái)表示.
XMPP服務(wù)模塊設(shè)計(jì)重點(diǎn)在于,Android客戶(hù)端和服務(wù)端的數(shù)據(jù)傳輸過(guò)程細(xì)節(jié)仍需要一系列結(jié)構(gòu)的設(shè)計(jì),包括連接的管理、認(rèn)證管理以及出席狀態(tài)的管理等等.XMPP服務(wù)模塊是可以獨(dú)立運(yùn)行的服務(wù),不依賴(lài)于HTTP服務(wù),當(dāng)服務(wù)啟動(dòng)之后,會(huì)有一系列的實(shí)例對(duì)象被生成,常駐在服務(wù)器的內(nèi)存中.一種最佳的實(shí)踐是使用容器來(lái)管理這些實(shí)例化的對(duì)象,Spring IOC在實(shí)例對(duì)象管理方法做的比較好,所以,XMPP服務(wù)模塊在設(shè)計(jì)的時(shí)候,考慮使用IOC容器.
服務(wù)端的HTTP服務(wù)是典型的B/S結(jié)構(gòu)的Web應(yīng)用,已經(jīng)有很多的成熟的框架供使用,目前比較流行的是SSH方案.

圖2 推送系統(tǒng)結(jié)構(gòu)設(shè)計(jì)
本文使用XMPP協(xié)議作為底層的通訊協(xié)議,對(duì)協(xié)議的內(nèi)容、通訊規(guī)程和語(yǔ)法規(guī)則做了做深入的剖析,在此基礎(chǔ)之上,對(duì)Android消息推送進(jìn)行了需求分析,然后對(duì)支持該協(xié)議的客戶(hù)端和服務(wù)端進(jìn)行了概要設(shè)計(jì)和系統(tǒng)結(jié)構(gòu)設(shè)計(jì),有利于其他項(xiàng)目集成并實(shí)現(xiàn)消息推送功能.