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