舒玉坤,張國祥
(1.湖北師范大學 數學與統計學院,湖北 黃石 435002 ; 2.湖北師范大學 物理與電子科學學院,湖北 黃石 435002)
全雙工多線程套接字通信的研究與實現
舒玉坤1,張國祥2
(1.湖北師范大學 數學與統計學院,湖北 黃石 435002 ; 2.湖北師范大學 物理與電子科學學院,湖北 黃石 435002)
對網絡環境中分布式進程通信的特點分析,借助JAVA對多線程套接字通信的支持,在Android平臺下,使用JAVA語言編程實現了全雙工多線程套接字通信,該方法安全,快捷,方便,具有一定的實用性。
JAVA; 客戶端/服務器; 套接字;多線程;通信
計算機網絡是分布在不同地理位置的多臺自治計算機系統的集合,這種自治表現為“獨立”,即每臺計算機的操作和資源,都由自身的操作系統來管理,用戶共享的網絡資源通過網絡環境中的分布式進程通信來實現;而單機系統中的通信則體現為程序在時間上嚴格按照次序執行(靜態),進程是一個程序對某個數據集的執行過程(動態),要保證通信的正常進行,必須對進程創建、撤銷和狀態轉換進行控制。可見網絡進程通信與單機進程通信的本質區別是網絡中的主機具有高度的自治性;不同的主機沒有一個統一的高層操作系統進行全局控制、調度與管理,因此網絡環境下分布式進程通訊需要解決進程命名與尋址方式,多重協議的識別,進程間的相互作用等問題。為此,在UNIX中引入五元組(或一個相關association)即協議、本地地址、本地端口號、遠程地址、遠程端口號來完整標識一個進程。
在TCP/IP中,進程間相互作用采用客戶端/服務器模式,即用client/server分別表示相互通信的兩個應用程序的進程,客戶向服務器發出服務請求,服務器響應客戶的請求,提供客戶所需要的服務,由于網絡資源分布的不均勻性以及進程通信的異步性,有必要建立一個機制,為進程之間建立連接,在進程交換數據的過程中維護連接,為數據交換提供同步控制與協調。
使用TCP/IP協議的應用程序,一般用UNIX BSD的套接字(Socket)來實現網絡進程之間的通信,按照UNIX思想就是“一切皆文件”,都可以用“打開”、“讀/寫”、“關閉”等模式來操作,Socket就是該模式的一個具體實現,是一種特殊的文件,通過socket()、bind()、listen()、connect()、accept()、read()、write()、close()函數來實現。
在網絡中應用層可以利用Socket對應的函數建立進程的連接,實現數據交換,因為Socket本身是面向client/server模式設計的,針對客戶和服務器的不同程序提供了不同Socket系統調用,客戶機可隨機申請一個Socket,服務器使用熟知的Socket,客戶可以隨機向服務器發出請求,服務器提供相應的服務。
4.1 JAVA對多線程通信的支持
JAVA是常用的網絡編程語言之一,它本身提供了Thread類,封裝了有關線程的控制,負責線程的啟動運行、休眠、掛起、恢復、退出和終止,以及線程優先級的控制,同時使用管程機制(monitor)來控制JAVA多線程的同步,提供3個標準Object類方法wait()、notify()和notifyAll()來實現線程之間的控制轉移,以防止在一個線程已得到了資源,而其它線程無休止的“忙等待”,消耗CPU資源,以解決“死鎖”的問題。 為保證客戶和服務器的正常連接,Socket通過三次握手來實現連接,如圖1所示:

圖1 Socket三次握手
從圖1中可知,當客戶端調用connect()時,觸發了連接請求,向服務區發出SYN J包,使connect進入阻塞狀態,服務器監聽到連接請求后,調用Accept()接收請求,并向客戶發送SYN K,ACK J+1,這時Accept進入阻塞狀態,客戶收到服務器SYN K,ACK j+1后,并對SYN K進行確認,服務器收到ACK k+1時,Accept(返回)三次握手完成,連接建立成功。
4.2 多線程套接通信的實現
一個進程是一個獨立的運行環境,可以看作一個程序或者一個應用,而線程是在進程中執行的一個任務,Java運行環境是一個包含了不同的類和程序的單一進程。線程可以被稱為輕量級進程,線程需要較少的資源來創建和駐留在進程中,并且可以共享進程中的資源。在多線程程序中,多個線程被并發的執行以提高程序的效率,CPU不會因為某個線程需要等待資源而進入空閑狀態。多個線程共享堆內存,因此創建多個線程去執行一些任務會比創建多個進程更好。
JAVA有兩種創建線程的方法:一是實現Runnable接口,然后將它傳遞給Thread的構造函數,創建一個Thread對象;二是直接繼承Thread類,并調用了Thread的run()方法,本文采用第二種方法,在客戶端程序中,首先通過mReceiveThread = new ReceiveThread(clientSocket),然后,為了在新的線程中執行,需要使用mReceiveThread.start()開啟線程;在服務器程序中,首先通過mAcceptThread = new AcceptThread(),然后使用mAcceptThread.start()開啟線程。在Java中新建一個線程時,它的狀態是New,當調用線程的start()方法時,狀態被改變為Runnable,線程調度器會為Runnable線程池中的線程分配CPU時間并且將它的狀態置為Running。當然也可以使用Thread類的Sleep()方法讓線程暫停一段時間,但不會讓線程終止,一旦從休眠中喚醒線程,線程的狀態將會被改變為Runnable,并且根據線程調度,它將得到執行。如圖2所示:

圖2 客戶連接請求與服務器監聽請求及信息收發
線程調度是一個操作系統服務,它負責為Runnable狀態的線程分配CPU時間,一旦創建一個線程并啟動它,它的執行便依賴于線程調度器的實現,CPU分配給可用的Runnable線程時間片,分配CPU時間可以基于線程優先級或者線程等待的時間,線程調度并不受Java虛擬機控制。
在程序實現中需要注意的是,在安卓系統2.3的系統上通信正常,但在4.0以上系統需要附加以下代碼,否則出錯。
StrictMode.setThreadPolicy(new StrictMode
.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode
.VmPolicy
.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedSqlLiteObjects()
.penaltyLog()
.penaltyDeath()
.build());
同時還要在AndroidManifest.xml中開放以下權限:
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.CHANGE_WIFI_STATE
程序實現客戶與服務器收發信息界面如圖3所示:界面為中文繁體,可轉換為中文簡體,在通信的過程中,為防止信息出現亂碼,可通過new String(this.information, "編碼方式").trim()進行編碼轉換,以保證通信的雙方編碼一致。

圖3 客戶與服務器收發信息界面
[1]吳功宜. 計算機網絡高級教程[M]. 北京:清華大學出版社,2007.
[2]Richard Stevens W. UNIX網絡編程(第2版) [M].北京:清華大學出版社,1999.
[3]Andrew S, Tanenbaum. Computer Networks (Third Edition) [M].北京:清華大學出版社,1998.
[4]Sayed Y, Hashimi, Satya Komatineni. 精通Android2[M]. 北京:人民郵電出版社,2010.
[5]吳亞峰,蘇亞光.Android應用案例開發大全[M].北京:人民郵電出版社,2011.
[6]張 斌,高 波. Linux網絡編程 [M].北京:清華大學出版社,2000.
[7]陳 浩.JAVA編程入門與提高 [M].北京:機械工業出版社,2011.
Research and implementation of full duplex multi-threadedsocket communication
SHU Yu-kun1,ZHANG Guo-xiang2
(1.College of Mathematics and Statistics,Hubei Normal University,Huangshi 435002,China;2. College of Physics and Electronics Science,Hubei Normal University,Huangshi 435002,China;)
Based on the characteristics of distributed interposes communication in network environment, With the help of JAVA support for multithreaded socket communication, using JAVA programming to realize full duplex multithread socket communication in the Android platform, the method is safe, quick, convenient and has a certain practicality.
JAVA; client / server; socket; multi thread; communication
2016—02—25
舒玉坤(1984— ),女,湖南溆浦人,助理實驗師、碩士,主要研究方向為微電子與信息技術.
TP393
A
2096-3149(2017)02- 0005-04
10.3969/j.issn.2096-3149.2017.02.002