馬玉春,劉 雍,喬麗娟,汪文彬
?
Android平臺(tái)下的TCP客戶機(jī)教學(xué)設(shè)計(jì)
馬玉春,劉 雍*,喬麗娟,汪文彬
(海南熱帶海洋學(xué)院海南省嵌入式系統(tǒng)重點(diǎn)實(shí)驗(yàn)室,海南 三亞 572022)
移動(dòng)互聯(lián)網(wǎng)正進(jìn)入高速普及期,成功的產(chǎn)品和服務(wù)模式不斷向其他產(chǎn)業(yè)領(lǐng)域延伸滲透,其中最重要的技術(shù)之一就是數(shù)據(jù)的傳輸與處理。本文在Android平臺(tái)下對(duì)TCP通信任務(wù)進(jìn)行分解,結(jié)合多線程技術(shù)、消息處理、數(shù)據(jù)編碼與校驗(yàn)技術(shù)剖析了一個(gè)通用多功能TCP客戶機(jī)測(cè)試軟件的實(shí)現(xiàn)過程,從而達(dá)到較好的教學(xué)效果。
Android;TCP客戶機(jī);多線程;消息;編碼;校驗(yàn)
移動(dòng)互聯(lián)網(wǎng)廣泛應(yīng)用于眾多領(lǐng)域,作為具體表現(xiàn)形式,可以用Android手機(jī)作為TCP客戶機(jī)監(jiān)測(cè)遠(yuǎn)程對(duì)象的狀態(tài)或進(jìn)行遠(yuǎn)程控制。TCP客戶機(jī)需要跟TCP服務(wù)器建立連接,然后在后臺(tái)接收數(shù)據(jù),這涉及多線程的處理,另外對(duì)于一些耗時(shí)的工作,也必須采用多線程技術(shù),否則容易導(dǎo)致APP崩潰。主線程與TCP客戶機(jī)中運(yùn)行的線程不在同一個(gè)空間,客戶機(jī)收到的數(shù)據(jù)不能直接發(fā)送到主線程供分析和處理,必須通過消息機(jī)制作為中介來完成此項(xiàng)工作。對(duì)于POP3協(xié)議,采用的是帶回車換行作為結(jié)尾碼的文本類型的協(xié)議;而對(duì)于遠(yuǎn)程控制,則經(jīng)常采用帶校驗(yàn)碼與結(jié)尾碼的字節(jié)型協(xié)議[1]。本文創(chuàng)建一個(gè)通用的TCP類,結(jié)合消息機(jī)制和多線程技術(shù),既可以用來開發(fā)TCP客戶機(jī)應(yīng)用,又可以用來開發(fā)TCP服務(wù)器應(yīng)用;TCP類與數(shù)據(jù)的編碼與校驗(yàn)相結(jié)合,完成一個(gè)通用TCP客戶機(jī)軟件工具,可以完成多項(xiàng)工作,具體功能將在軟件測(cè)試方面進(jìn)行展開,其工作模型如圖1所示。
圖1 TCP客戶機(jī)工作模型
消息處理類Handler允許發(fā)送和處理Message或Runnable對(duì)象到其所在線程的消息隊(duì)列中,每個(gè)Handler類的實(shí)例都與一個(gè)線程及其消息隊(duì)列相聯(lián)系,當(dāng)創(chuàng)建一個(gè)Handler實(shí)例時(shí),這個(gè)實(shí)例就綁定到創(chuàng)建該實(shí)例的線程和消息隊(duì)列中。Handler類采用post方法將Runnable對(duì)象發(fā)送到所在線程的消息隊(duì)列中排隊(duì)執(zhí)行,可以立即發(fā)送,也可以延遲發(fā)送,延遲的時(shí)間單位為毫秒。Handler類通過send-Message方法將消息發(fā)送到所在線程,可以立即發(fā)送(空)消息,也可以延遲發(fā)送(空)消息,消息中含有需要傳遞到主線程中的數(shù)據(jù)以及消息識(shí)別代碼。Handler的handleMessage是一個(gè)自動(dòng)回調(diào)方法,需要根據(jù)實(shí)際功能重寫,圖1中TCP客戶機(jī)在主線程的handleMessage方法中處理TCP客戶機(jī)類的對(duì)象所收到的數(shù)據(jù)[2]。
盡管Message類有默認(rèn)的構(gòu)造方法,但通常采用Handler對(duì)象的obtainMessage方法來獲得并初始化一個(gè)Message對(duì)象,指定表1所示的參數(shù),其中what用來標(biāo)識(shí)消息,如果需要向主線程傳遞整型變量,直接設(shè)置arg1和arg2的值;如果不需要,缺省設(shè)置為0即可。obj是Object類型,也就是通用類型,可以是任何類型的數(shù)據(jù),但不能是基類型,因而,字節(jié)數(shù)組必須轉(zhuǎn)換成ByteBuffer類型的對(duì)象。
表1 Message類的常用屬性
Tab.1 Common attributes of message class
在教學(xué)設(shè)計(jì)上,可以安排一個(gè)簡(jiǎn)單的時(shí)鐘軟件項(xiàng)目,用Handler對(duì)象每過1秒鐘發(fā)送一個(gè)空消息,在主線程的handleMessage方法中更新用戶界面中的時(shí)鐘信息。也可以安排一個(gè)監(jiān)控手機(jī)返回鍵的軟件項(xiàng)目,避免不小心按下返回鍵即退出應(yīng)用軟件。當(dāng)?shù)谝淮伟聪路祷劓I時(shí),過兩秒復(fù)位返回鍵,否則,在兩秒之內(nèi)第二次按下返回鍵即退出當(dāng)前軟件。這兩個(gè)軟件項(xiàng)目都比較簡(jiǎn)單,而且可以用來較好地理解消息機(jī)制[3]。
在Android系統(tǒng)中,所有的操作默認(rèn)情況下都是在主線程中進(jìn)行,對(duì)于一些比較耗時(shí)的操作或者需要并行完成的操作,通常使用一個(gè)獨(dú)立的線程來執(zhí)行。獲取IP地址是一個(gè)耗時(shí)的工作,需要使用多線程,并在其中使用上一節(jié)的消息機(jī)制將IP地址提交到主線程。
這里以獲取Wi-Fi的IP地址為例。在多線程對(duì)象中調(diào)用getSystemService方法傳入系統(tǒng)參數(shù)從而獲得WifiManager對(duì)象,然后調(diào)用該對(duì)象的getConnectionInfo方法獲取連接信息,從而進(jìn)一步調(diào)用getIpAddress方法獲取int類型的IP地址,可以將此IP地址轉(zhuǎn)換為文本形式的格式化IP地址。在主線程中通過Thread對(duì)象的start方法啟動(dòng)該多線程,在其中啟用Handler對(duì)象的消息機(jī)制,將文本形式的IP地址傳送到主線程進(jìn)行顯示[4]。
在教學(xué)設(shè)計(jì)上,可以安排一個(gè)用于獲取IP地址的多線程軟件項(xiàng)目,在主線程啟動(dòng)多線程獲取IP地址,通過handleMessage回調(diào)方法在主線程中獲取IP地址信息并顯示。如果不使用多線程技術(shù),則軟件將直接崩潰。該項(xiàng)目邏輯簡(jiǎn)單,但是,能夠較好地說明多線程的作用。
文獻(xiàn)[5]設(shè)計(jì)了一個(gè)TCP服務(wù)器類,并在此基礎(chǔ)之上構(gòu)建了一個(gè)TCP服務(wù)器軟件。TCP客戶機(jī)與TCP服務(wù)器有相似之處,都要建立連接,連接成功后即采用多線程技術(shù)在后臺(tái)讀取收到的數(shù)據(jù),然后通過消息機(jī)制將收到的數(shù)據(jù)提交到主線程。TCP通信具有普遍性,這里創(chuàng)建一個(gè)Library共享類庫項(xiàng)目,在其中創(chuàng)建一個(gè)TcpClientServer類,使其既支持TCP客戶機(jī),又支持TCP服務(wù)器。
表2 TcpClientServer類中的自定義消息
Tab.2 Custom messages in the TcpClientServer class
TcpClientServer類中所定義的消息如表2所示,無論是工作在客戶機(jī)或服務(wù)器模式,如果軟件收到"Interval?! ",則立即返回"OK! ",同時(shí)向主線程發(fā)送消息MSG_ReplyOK,該方法從接收數(shù)據(jù)到返回?cái)?shù)據(jù),中間沒有耽誤任何時(shí)間,因而,可以用來測(cè)試客戶機(jī)與服務(wù)器之間的時(shí)間距離,為軟件研發(fā)提供參數(shù)設(shè)置支持。其他為常規(guī)消息,主線程收到MSG_Connected消息,可以進(jìn)入發(fā)送數(shù)據(jù)環(huán)節(jié);收到MSG_Closed消息即可釋放資源;收到MSG_ DataArrived消息,即可提取表1所示的obj數(shù)據(jù),利用下一節(jié)的編碼與校驗(yàn)技術(shù)對(duì)數(shù)據(jù)進(jìn)行檢查,如果正確再執(zhí)行相關(guān)操作。
在TcpClientServer類中設(shè)置兩個(gè)構(gòu)造函數(shù),都設(shè)置Handler參數(shù),用于進(jìn)行消息傳遞。兩個(gè)構(gòu)造函數(shù)不同部分是,如果僅設(shè)置端口地址,則TcpClie-ntServer類作為TCP服務(wù)器使用;如果設(shè)置了主機(jī)名稱(或IP地址)和端口地址,則TcpClient-Server類作為TCP客戶機(jī)使用。在服務(wù)器工作模式下,初始化ServerSocket類時(shí)傳入端口地址,得到Server-Socket對(duì)象,再調(diào)用accept方法,客戶機(jī)與服務(wù)器連接成功,即可得到Socket對(duì)象;在客戶機(jī)工作模式下,直接初始化Socket類得到其實(shí)例,然后調(diào)用其connect方法,傳入遠(yuǎn)程主機(jī)名稱、端口地址以及連接延遲三個(gè)參數(shù),即可與遠(yuǎn)程服務(wù)器建立連接[6]。本文研發(fā)的通用客戶機(jī)測(cè)試軟件采用后一種工作模式。
得到Socket類的實(shí)例后,如果采用文本協(xié)議進(jìn)行TCP通信,則調(diào)用其getInputStream方法得到輸入流對(duì)象,然后依次獲得InputStreamReader和Buff-eredReader對(duì)象,最后啟動(dòng)多線程通過Buffered-Re-ader對(duì)象在后臺(tái)讀取文本數(shù)據(jù),通過MSG_Data--Arrived消息將收到的數(shù)據(jù)提交到主線程。相應(yīng)地,通過Socket類的實(shí)例的getOutputStream方法得到輸出流對(duì)象,然后依次獲得Output-Stream-Writer和Bu-fferedWriter對(duì)象,這樣,主線程即可通過Bu-fferedWriter對(duì)象發(fā)送文本數(shù)據(jù)。如果采用字節(jié)協(xié)議進(jìn)行TCP通信,則采用BufferedInput-Stream對(duì)象在后臺(tái)讀取字節(jié)數(shù)據(jù),主線程則通過BufferedOut-putStream對(duì)象發(fā)送字節(jié)數(shù)據(jù)。
在教學(xué)設(shè)計(jì)上,先實(shí)現(xiàn)客戶機(jī)工作模式,與POP3服務(wù)器連接后,實(shí)現(xiàn)文本數(shù)據(jù)的接收與發(fā)送,再進(jìn)一步過渡到字節(jié)數(shù)據(jù)的接收與發(fā)送。對(duì)應(yīng)地,接著實(shí)現(xiàn)服務(wù)器工作模式,跟完成的客戶機(jī)軟件建立連接,分別實(shí)現(xiàn)文本數(shù)據(jù)的接收與發(fā)送,再實(shí)現(xiàn)字節(jié)數(shù)據(jù)的接收與發(fā)送。當(dāng)客戶機(jī)軟件和服務(wù)器軟件都實(shí)現(xiàn)以后,將TCP客戶機(jī)類與服務(wù)器類綜合為一個(gè)類,即TcpClientServer,這樣可以方便代碼的維護(hù)。
TcpClientServer類既可以收發(fā)文本數(shù)據(jù),也可收發(fā)字節(jié)數(shù)據(jù)。對(duì)于一個(gè)字節(jié),有多種不同表達(dá)方式,分別用于不同的場(chǎng)景,如表3所示(普通字符列的“-”表示不可見字符)。如果某設(shè)備采用字節(jié)型協(xié)議,為了對(duì)該設(shè)備進(jìn)行測(cè)試,則需要將收到的數(shù)據(jù)轉(zhuǎn)換為16進(jìn)制字符串形式;而字節(jié)數(shù)據(jù)也可以用16進(jìn)制字符串來表示,因?yàn)樽址奖氵M(jìn)行連接,在需要發(fā)送的時(shí)候,再轉(zhuǎn)換為字節(jié)數(shù)據(jù);如果客戶機(jī)與服務(wù)器之間采用文本協(xié)議,則直接采用“普通字符”即可。
表3 字節(jié)的不同表示方法
Tab.3 Different representations of bytes
為了適應(yīng)各種數(shù)據(jù)的傳輸,在Library類庫項(xiàng)目中創(chuàng)建ByteProcess類,用bytesToHexChars靜態(tài)函數(shù)實(shí)現(xiàn)字節(jié)數(shù)組到16進(jìn)制字符串的轉(zhuǎn)換,用hexCharsToBytes靜態(tài)函數(shù)實(shí)現(xiàn)16進(jìn)制字符串到字節(jié)數(shù)組的轉(zhuǎn)換;用enStringToBytes靜態(tài)函數(shù)實(shí)現(xiàn)普通字符串到字節(jié)數(shù)組的轉(zhuǎn)換,通過bytesToEnString靜態(tài)函數(shù)實(shí)現(xiàn)字節(jié)數(shù)組到普通字符串的轉(zhuǎn)換;用enStringToHexChars靜態(tài)函數(shù)實(shí)現(xiàn)普通字符到16進(jìn)制字符串的轉(zhuǎn)換,通過hexCharsToEnString靜態(tài)函數(shù)實(shí)現(xiàn)16進(jìn)制字符串到普通字符串的轉(zhuǎn)換。
編碼只是解決了數(shù)據(jù)傳輸?shù)男问?,而不能保證數(shù)據(jù)傳輸?shù)恼_性,因而,需要對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行校驗(yàn)。TCP/IP協(xié)議采用累加求補(bǔ)方式,即對(duì)于需要發(fā)送的字節(jié)數(shù)組,累加所有字(即每?jī)蓚€(gè)字節(jié)作為一個(gè)字),然后將結(jié)果的低位字與高位字相加,最后將結(jié)果取反并取低位字,此即累加求補(bǔ)校驗(yàn)碼[2]。計(jì)算所得的校驗(yàn)碼一般放在需要發(fā)送的數(shù)據(jù)后面,對(duì)方收到數(shù)據(jù)后,重新計(jì)算校驗(yàn)碼,如果收到的校驗(yàn)碼和計(jì)算所得校驗(yàn)碼相等,則說明收到的數(shù)據(jù)正確,就進(jìn)一步處理,否則直接丟棄。累加求補(bǔ)校驗(yàn)碼有其特殊性,對(duì)包含累加求補(bǔ)校驗(yàn)碼的數(shù)據(jù)包進(jìn)行驗(yàn)證,只要整體校驗(yàn)碼計(jì)算結(jié)果為0,即說明數(shù)據(jù)正確。相似地,異或校驗(yàn)碼和循環(huán)冗余校驗(yàn)碼也有此特性。
累加和校驗(yàn)碼只需要將待發(fā)送的字節(jié)進(jìn)行累加取低字節(jié),異或校驗(yàn)碼只需要將待發(fā)送的字節(jié)逐個(gè)異或。循環(huán)冗余(CRC)校驗(yàn)碼的算法比較復(fù)雜,其基本思想是將需要發(fā)送的數(shù)據(jù)包當(dāng)作一個(gè)系數(shù)為0或1的多項(xiàng)式。多項(xiàng)式的算術(shù)運(yùn)算采用代數(shù)域的理論規(guī)則,以2為模進(jìn)行,即加法沒有進(jìn)位,減法沒有借位,加法與減法都等同于異或。長(zhǎng)除法與二進(jìn)制中的長(zhǎng)除運(yùn)算類似,只是減法按照模2進(jìn)行[7]。在Library類庫項(xiàng)目中,添加Parity類,分別實(shí)現(xiàn)以上各種校驗(yàn)碼的計(jì)算及數(shù)據(jù)包的校驗(yàn)。
在編碼與校驗(yàn)的教學(xué)設(shè)計(jì)上,設(shè)置斷點(diǎn)比較高效,采用“Debug As”模式跟蹤數(shù)據(jù)的變化,逐個(gè)完成數(shù)據(jù)編碼轉(zhuǎn)換函數(shù)及校驗(yàn)碼的計(jì)算過程。POP3之類的應(yīng)用層協(xié)議需要添加回車換行符作為結(jié)尾碼,有的設(shè)備需要使用回車符作為結(jié)尾碼[8]。結(jié)尾碼的添加與檢驗(yàn)比較簡(jiǎn)單,這里不再贅述。
新建TcpClient項(xiàng)目,引用以上Library共享類庫,依次導(dǎo)入TcpClientServer類、ByteProcess類和Parity類,設(shè)計(jì)好軟件界面,即可快速搭建一個(gè)通用TCP客戶機(jī)軟件,其運(yùn)行效果如圖2所示。圖2中左側(cè)用來顯示數(shù)據(jù),上面的單行文本框顯示當(dāng)前數(shù)據(jù),下面的多行文本框顯示歷史數(shù)據(jù)。右側(cè)為參數(shù)設(shè)置,這里連接的是163的POP3服務(wù)器,顯示模式(Display Mode)為字符型(Char),校驗(yàn)方式(Parity Sort)為無校驗(yàn)碼(None),結(jié)尾碼(End Mark)為回車換行(CRLF),自動(dòng)大寫待發(fā)送的數(shù)據(jù),收到數(shù)據(jù)以后播放提示音。圖中為點(diǎn)擊【Connect】按鈕與POP3服務(wù)器建立連接以后的會(huì)話情況。
圖2 TCP客戶機(jī)軟件界面
將計(jì)算機(jī)當(dāng)做一個(gè)協(xié)議轉(zhuǎn)換器,手機(jī)與計(jì)算機(jī)同時(shí)處于一個(gè)無線Wi-Fi網(wǎng)段內(nèi),計(jì)算機(jī)以TCP服務(wù)器的方式工作,則此TCP客戶機(jī)可以連接此TCP服務(wù)器[9]。計(jì)算機(jī)同時(shí)連接RS485工業(yè)控制總線的設(shè)備,協(xié)議轉(zhuǎn)換器將從手機(jī)TCP客戶機(jī)收到的信息轉(zhuǎn)發(fā)到RS485設(shè)備,再將RS485設(shè)備的響應(yīng)轉(zhuǎn)發(fā)到手機(jī)的TCP客戶機(jī),這樣即可用此TCP客戶機(jī)對(duì)多種編碼、校驗(yàn)碼類型的設(shè)備進(jìn)行測(cè)試[10]。其測(cè)試工作原理如圖3所示。
圖3 TCP客戶機(jī)用于測(cè)試RS485設(shè)備
本文從教學(xué)設(shè)計(jì)的角度,將知識(shí)點(diǎn)進(jìn)行分解,介紹了Android軟件設(shè)計(jì)中常用的消息機(jī)制和多線程技術(shù),并用于通用TCP類。通過對(duì)TCP客戶機(jī)與服務(wù)器的分析,將兩者綜合起來,共享其數(shù)據(jù)接收與發(fā)送功能,降低了軟件維護(hù)成本。最后引入編碼與校驗(yàn)技術(shù),使得TCP軟件傳輸?shù)臄?shù)據(jù)適應(yīng)多種編碼方式,又不失可靠性。采用移動(dòng)互聯(lián)網(wǎng)實(shí)現(xiàn)通用TCP客戶機(jī),可以對(duì)工業(yè)控制總線設(shè)備及基本的TCP應(yīng)用層協(xié)議進(jìn)行測(cè)試,有效增加了測(cè)試的便攜性。
[1] 王小科, 寇長(zhǎng)梅. Android入門經(jīng)典[M]. 機(jī)械工業(yè)出版社, 2013: 358-363.
[2] 馬玉春. 計(jì)算機(jī)監(jiān)控系統(tǒng)的仿真開發(fā)[M]. 北京: 國防工業(yè)出版社, 2015: 198-226, 21-24.
[3] 劉雍, 孫冰, 馬玉春. 基于消息驅(qū)動(dòng)的Android TCP服務(wù)器類的設(shè)計(jì)[J]. 海南熱帶海洋學(xué)院學(xué)報(bào). 2017(2): 59-63.
[4] 楊宗德, 劉雍, 呂光宏. Linux高級(jí)程序設(shè)計(jì)[M]. 第三版. 北京: 人民郵電出版社, 2012: 305-309.
[5] 馬玉春, 汪文彬, 李應(yīng)勇. 基于TCP客戶機(jī)的計(jì)算機(jī)監(jiān)控系統(tǒng)測(cè)試軟件的設(shè)計(jì)[J]. 軟件. 2014, 35(5): 1-3+12.
[6] 馬程, 魏怡卓, 曹瑜, 等. 老人意外跌倒遠(yuǎn)程智能監(jiān)控系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[J]. 軟件, 2018, 39(3): 209-217.
[7] 毛昊. 一種服務(wù)于Android 移動(dòng)設(shè)備的自適應(yīng)滾屏技術(shù)[J]. 軟件, 2018, 39(3): 145-149.
[8] 呂媛媛, 李可. 移動(dòng)端應(yīng)用設(shè)計(jì)中的響應(yīng)式實(shí)現(xiàn)方法[J]. 軟件, 2016, 37(0): 107-109.
[9] Guolin. Android ListView工作原理完全解析, 帶你從源碼的角度徹底理解. 2015.
[10] 耿祥義, 張躍平. Android手機(jī)程序設(shè)計(jì)實(shí)用教程[M]. 清華大學(xué)出版社. 2013: 258-261.
Instructional Design of TCP Client on Android Platform
MA Yu-chun, LIU Yong*, QIAO Li-juan, WANG Wen-bin
(Hainan Key Laboratory of Embedded Systems at Hainan Tropic Ocean University, Sanya, Hainan 572022, China)
The mobile Internet is entering a period of high-speed popularization. Successful products and service models continue to penetrate into other industry fields. However, one of the most important technologies is the transmission and processing of data. This paper analyses the TCP communication on Android platform, including message processing, thread technology, data encoding and verification, in order to display the desired teaching effect. Finally, the general TCP client is developed and tested based on these technologies.
Android; TCP client; Thread; Message; Encode; Verification
TP311.56
A
10.3969/j.issn.1003-6970.2018.10.004
海南省高等學(xué)校教育教學(xué)改革研究項(xiàng)目(批準(zhǔn)號(hào):Hnjg2018-57);三亞市院地科技合作項(xiàng)目(批準(zhǔn)號(hào):2015YD03)
馬玉春(1969-),男,教授,中國計(jì)算機(jī)學(xué)會(huì)高級(jí)會(huì)員(編號(hào):06544S),主要研究方向:移動(dòng)應(yīng)用與計(jì)算機(jī)監(jiān)控技術(shù);喬麗娟(1981-),女,副教授,主要研究方向:計(jì)算機(jī)網(wǎng)絡(luò)與移動(dòng)應(yīng)用;汪文彬(1969-),男,教授,主要研究方向:進(jìn)化計(jì)算與軟件測(cè)試。
劉雍(1979-),女,副教授,主要研究方向:移動(dòng)應(yīng)用與嵌入式系統(tǒng)。
馬玉春,劉雍,喬麗娟,等. Android平臺(tái)下的TCP客戶機(jī)教學(xué)設(shè)計(jì)[J]. 軟件,2018,39(10):14-17