許姍姍
(廈門軟件職業技術學院,福建廈門 361000)
隨著科技的迅速發展,移動網絡以及智能手機的普及讓人們的生活發生了巨大的變化。Android網絡開發就是實現不同終端之間的通信,其中一個應用就是把復雜的數據操作運算放在計算機終端,來實現手機的高功能運行[1]。
目前,基于TCP/IP協議的Socket通信是廣泛應用的通信協議之一。基于TCP/IP協議的Socket通信,是通過指定IP地址和port號,采用c/s模式建立TCP協議下的兩個通信進程間的連接,實現可靠的雙向通信[2]。生活中越來越多的廠商會將物聯網技術與智能硬件組合在同一個局域網內,由網關通過指令統一控制智能硬件。例如,火焰報警信息傳遞、監控點的智能相機等平臺,就是采用高實時性的基于TCP協議的Socket通訊技術,將傳感器數據實時送達。人們平常使用的網絡聊天程序、迅雷下載程序等都需要用到Socket通信技術。
國內外對于Socket的研究主要包括基于TCP/IP協議關于Socket通信程序的研究、Sokcet的網絡編程研究與實現等,現在已取得了較為成熟的成果[3]。但在教學中經常遇到了以下的問題:在使用Android studio開發環境下,開發兩個APP,如果將它們各自部署到運用Android系統的手機上,在同一個Wi-Fi下是可以成功通信的。但在課堂上這樣操作會比較麻煩,通常學生很少攜帶兩部手機。如果能快速地將這兩個APP發布到同一臺電腦的不同Android模擬器上進行通信,則會既簡單又高效,這是本文研究的主要思路。
TCP/IP協議為傳輸控制協議/因特網互聯協議,是Internet最基本的協議,也是Internet國際互聯網絡的基礎,由網絡層的IP協議和傳輸層的TCP協議組成[4]。Socket定義了一些規范,我們只需要遵循Socket的規定去編程即可。
Socket是應用層與TCP/IP協議簇通訊的中間抽象層,Socket是一組接口,通常被稱作“套接字”[5]。簡單來說,Socket提供了程序內部與外界通信的端口,并為通信雙方提供了數據傳輸通道[6]。基于Sokcet的網絡編程的主要操作流程如下:
(1)調用類ServerSocket的ServerSocket(int aport)方法創建一個ServerSocket對象,并綁定到指定端口。(2)調用accept()方法,監聽連接請求,如果客戶端請求連接,則接受連接,并返回一個Socket對象。(3)通過Socket對象的getInputStream()和Socket對象的getOutputStream()方法獲得輸出流和輸入流,程序開始進入數據的接收和發送[7]。(4)關閉流、ServerSocket對象及Socket對象。
(1)調用Socket(InetAddress dstAddress,int dstPort)創建一個Socket對象,并連接到服務器端。(2)通過Socket對象.getInputStream()和Socket對象.getOutputStream()方法獲得輸出流和輸入流,開始進入數據的接收和發送。(3)關閉流和Socket對象。
套接字客戶端與服務端通信的具體流程圖如1所示。

圖1 套接字客戶端與服務端通信的流程圖
計算機之間可以通過IP地址進行通信,IP地址都是唯一的。Android模擬器提供了一個特殊的IP地址10.0.2.2,如果同一臺計算機開啟了兩個Android模擬器,那這兩個模擬器的IP是一樣的,都是10.0.2.2。而IP相同的兩臺模擬器間如何通信是我們需要解決的問題。經過研究,通過端口重定向技術,可實現Android模擬器之間的通信。端口重定向技術的具體操作如下:
(1)先在“我的電腦”右鍵屬性,進入“高級系統設置”,選擇“高級”選項卡,進入“環境變量”,選擇系統變量名Path,將SDK中platform-tools所在的路徑復制粘貼進去。如圖2所示。

圖2 在系統變量Path中添加SDK的platform-tools所在路徑
(2)啟動兩個Android Studio自帶的模擬器,假設一個為emulator-5554,另一個為emulator-5556。將emulator-5554設定為服務器,將emulator-5556設定為客戶端。Android的模擬器有個特點,就是程序訪問網絡的時候只可以從模擬器連接到外界,但是卻無法從外界連接模擬器。用戶想要從外界連接上模擬器,需要將端口重定向[8]。首先在cmd中執行命令Telnet localhost 5554,遠程登錄服務器,如果提示該命令無效,則要進入控制面板,單擊“程序和功能”類別,打開“Windows功能”對話框,勾選“Telnet客戶端”組件,具體操作如圖3所示。

圖3 打開Telnet客戶端
接著重新執行命令Telnet localhost 5554,命令行窗體提示“正在連接localhost...”,這樣就可以遠程登錄服務器,出現一個標題為“Telnet localhost”的窗體,如圖4所示。

圖4 遠程登錄服務器
接下來輸入命令“help”,查看列表中是否有“redir”命令,如果沒有,則必須進行身份認證,方法很簡單,只需通過上面窗體中的“C∶UsersAdministrator。emulator_console_auth_token”這串路徑找到對應文件,復制文件中的字符串,通過命令“auth字符串”,就能通過認證,如圖5所示。

圖5 通過命令“auth字符串”進行身份證
最后再次輸入命令“help”,就能在列表中看到“redir”命令。輸入命令“redir add tcp∶1112∶1111”,即可完成端口重定向,如圖6所示。其中,1112是客戶端new Socket(“10.0.2.2”,1112)的端口,1111是服務端new ServerSocket(“1111”)的端口。完成這步端口重定向后,外界也可以連接上模擬器,即模擬器emulator-5556可以連接上emulator-5554了。

圖6 使用“redir”命令進行端口重定向
創建兩個Android應用程序:一個作為服務端程序;一個作為客戶端程序。
(1)服務端程序關鍵代碼如下:
serverSocket=new ServerSocket(1111);//綁定到指定端口
Log.i("ServerActivity","服務器啟動了");
socket=serverSocket.accept();//等待Socket請求,直到連接被打開。
Log.i("ServerActivity","有客戶連接到服務器");
服務端綁定到指定的端口為1111,當用戶點擊按鈕、啟動服務端后,程序執行ServerSocket對象的accept()方法,監聽連接請求,如果客戶端請求連接,則服務端接受連接,并返回一個Socket對象。建立連接后程序通過socket.getOutputStream()和socket.getInputStream()進行數據的傳輸。
(2)客戶端程序關鍵代碼如下:
socket=new Socket("10.0.2.2",1112);//以本機另一個模擬器為服務端,則IP地址是10.0.2.2。
客戶端綁定到指定的端口為1112,連接到本地的模擬器的IP為10.0.2.2。當用戶點擊按鈕,客戶端連接上服務器后,程序就可以通過socket.getOutputStream()和socket.getInputStream()進行數據的傳輸。
這里需要將模擬器的端口進行重定向,使用命令“redir add tcp∶1112∶1111”,具體用法上文有詳細說明。運行程序,將服務端程序運行在模擬器emulator-5554上,將客戶端程序運行在模擬器emulator-5556上。點擊服務端界面的“啟動服務端程序”按鈕,客戶端界面會顯示“服務端:我已經啟動了”字樣,點擊客戶端界面的“連接服務端程序”按鈕,服務端界面會顯示“客戶端:我已連接上你了”字樣,這時表明服務端和客戶端已連接成功,可以進行通信了。運行效果如圖7和圖8所示。

圖7 服務端界面

圖8 客戶端界面
本文運用端口重定向技術實現了同一臺計算機上兩個Android模擬器間的通信,通過端口重定向技術使外界也能連接上模擬器。在教學中可以直接將應用程序部署到模擬器上進行網絡通信,解決了課堂上沒有太多真機可用于測試的問題,同時還可以應用于初創企業。目前運用Android系統的手機機型眾多,系統版本多,保證應用程序的兼容性是在應用上架前必做的測試之一。而兼容性測試對于網絡開發的初創企業而言是一大難題,可使用本文提出的模擬器間通信的方法先進行通信測試,再到一些網站上進行兼容性測試(例如,WeTest平臺就提供了移動端測試服務)。