宋曉莉,李宏
(1.中南大學(xué)軟件學(xué)院,湖南長沙410083;2.湖南工業(yè)職業(yè)技術(shù)學(xué)院,湖南長沙410208)
基于UNIX平臺(tái)下的Socket對話系統(tǒng)的設(shè)計(jì)
宋曉莉1,2,李宏1
(1.中南大學(xué)軟件學(xué)院,湖南長沙410083;2.湖南工業(yè)職業(yè)技術(shù)學(xué)院,湖南長沙410208)
Socket編程是用來解決網(wǎng)際間的進(jìn)程能夠進(jìn)行相互通信的問題。而Socket接口為進(jìn)程間的相互通信提供了一種新的方法,Socket接口不僅可以用在同一機(jī)器內(nèi)部進(jìn)程之間的相互通信,而且還能夠?qū)崿F(xiàn)網(wǎng)際之間的相互通信的功能。本文對相關(guān)理論進(jìn)行了討論與研究,并在此基礎(chǔ)上設(shè)計(jì)出一個(gè)對話系統(tǒng)。
Socket接口;對話系統(tǒng);TCP/IP
socket通常也被稱作為“套接字”[1],它的目的是用于描述IP地址和端口號,要想能夠更好的設(shè)計(jì)出線程模型,必須清楚了解socket的內(nèi)部環(huán)境和工作機(jī)理。Socket編程界面是基于4BSD UNIX下實(shí)現(xiàn)的,其目的就是用來解決網(wǎng)際間的進(jìn)程能夠進(jìn)行相互通信的問題。而Socket接口為進(jìn)程間的相互通信提供了一種新的方法,Socket接口不僅可以用在同一機(jī)器內(nèi)部進(jìn)程之間的相互通信,而且還能夠?qū)崿F(xiàn)網(wǎng)際之間的相互通信的功能。Socket的不同類型則實(shí)現(xiàn)了透明傳輸通信的功能。
Java程序設(shè)計(jì)語言取得成功的領(lǐng)域之一就是應(yīng)用于網(wǎng)絡(luò)中[2]。TCP/IP(傳輸控制協(xié)議/網(wǎng)間協(xié)議)是internet的主要協(xié)議之一,TCP/IP協(xié)議定義了計(jì)算機(jī)和外設(shè)進(jìn)行通信所使用的規(guī)則即語法、語意、定時(shí)。TCP/IP的模型即應(yīng)用層,傳輸層,網(wǎng)絡(luò)層,網(wǎng)絡(luò)接口層。大多數(shù)運(yùn)行在Internet上的應(yīng)用程序通常是被看成是TCP/IP協(xié)議模型的上一層。 如:ftp、http、smtp、pop3、telnet等等。
IP地址:是為連接Internet的每一臺(tái)計(jì)算機(jī)所分配的一個(gè)長達(dá)32bit地址,在Internet上每臺(tái)主機(jī)有且僅有一個(gè)IP地址。
在Java語言中,InterAddress類的功能是用來存儲(chǔ)主機(jī)在internet中IP地址的。
Java提供的網(wǎng)絡(luò)功能,大致可以分為三大類:
1.1.1 URL
URL是這三大功能中最高級別的一類,通過URL Java程序則可以從網(wǎng)絡(luò)上讀入數(shù)據(jù)或者是直接將數(shù)據(jù)送到網(wǎng)路上。
1.1.2 Socket
Socket是internet網(wǎng)絡(luò)中程序設(shè)計(jì)最為常用的一種方式。功能就是為兩個(gè)不同的進(jìn)程提供網(wǎng)絡(luò)通信信道。
1.1.3 Datagram
是更為低級的網(wǎng)絡(luò)傳輸方式,它的作用就是把數(shù)據(jù)的目的記錄在數(shù)據(jù)包中,然后直接把數(shù)據(jù)包放在網(wǎng)絡(luò)上進(jìn)行傳輸。
TCP/IP協(xié)議奠定了網(wǎng)絡(luò)通信的基石,對此,Java程序設(shè)計(jì)語言專門提供了一個(gè)Socket的類庫[3],將TCP協(xié)議通信的一些常用方法抽象出來。
在介紹TCP/IP協(xié)議通信的流程之前,先來對兩個(gè)重要的概念進(jìn)行聲明。
(1)客戶端:客戶端就是指發(fā)送TCP請求的并且為客戶提供本地服務(wù)的一些程序,客戶端一般是服務(wù)(比如數(shù)據(jù)查詢服務(wù))的請求者。
(2)服務(wù)器:服務(wù)器是指一個(gè)專門管理資源并且為用戶提供服務(wù)的一些程序或軟件。當(dāng)服務(wù)器接收到客戶端的請求之后(確保同客戶端的通信信道建立),服務(wù)器則會(huì)向客戶端提供客戶端所需的服務(wù)。服務(wù)器一般是提供服務(wù)并執(zhí)行服務(wù)的的,并向客戶端返回服務(wù)執(zhí)行的結(jié)果。
為了實(shí)現(xiàn)客戶端與服務(wù)器端的相互通信,客戶端首先將一個(gè)“SYN”數(shù)據(jù)包發(fā)送到服務(wù)器端。如果服務(wù)器收到了一個(gè)標(biāo)識(shí)是SYN標(biāo)記,這時(shí)服務(wù)器端將一個(gè)“SYN+ACK”數(shù)據(jù)包發(fā)送到請求服務(wù)的客戶端??蛻舳耸盏椒?wù)器的響應(yīng)即SYN+ACK信息后則立即會(huì)向服務(wù)器發(fā)送一個(gè)最終確認(rèn)消息息(ACK包)。至此客服端和服務(wù)器端建立起連接。這種通過SYN,SYN+ACK,ACK的一問一答的步驟就叫做TCP連接建立時(shí)的“三次握手”。這樣客戶端和服務(wù)器端就安全地建立起連接,這個(gè)連接將一直保持著活動(dòng)狀態(tài),直到超時(shí)或者客戶端或者是服務(wù)器端任何一方發(fā)出一個(gè)FIN(結(jié)束)信號。這種通信模式也叫客戶端/服務(wù)器(C/S)模式。
圖2.1三次握手
由此可見,客戶端和服務(wù)器端通過“三次握手”,雙方就建立起暢通的通信信道,在此信道上雙方能夠互相傳輸數(shù)據(jù)。
計(jì)算機(jī)網(wǎng)絡(luò)是指將各個(gè)自治的計(jì)算機(jī)連接起來以資源共享為目的的計(jì)算機(jī)集合。計(jì)算機(jī)網(wǎng)絡(luò)最基本的目的之一就是讓不同的計(jì)算機(jī)連接到一起,并實(shí)現(xiàn)相互“交談”或者“溝通”。一旦兩臺(tái)計(jì)算機(jī)都發(fā)現(xiàn)了對方,就可以展開不同計(jì)算機(jī)的相互通信。但它們通過什么樣的方式才能“發(fā)現(xiàn)”對方呢?我們可以以一個(gè)游戲?yàn)槔?,與在游樂園里做游戲一樣:一臺(tái)計(jì)算機(jī)要停留在某一個(gè)特定的地方,一直偵聽著其他計(jì)算機(jī)發(fā)出的信號,好像就是說:“嘿,你在哪里呢?”。那個(gè)這個(gè)時(shí)候停留的計(jì)算機(jī)則做出回應(yīng),我們把停留在某個(gè)特定的地方的計(jì)算機(jī)叫做服務(wù)器端。即Server;到處“找人”的計(jì)算機(jī)則稱作是客戶機(jī)端(Client)??蛻魴C(jī)端和服務(wù)器端之間的區(qū)別就是只有在客戶機(jī)試圖同服務(wù)器連接的時(shí)候才會(huì)表現(xiàn)出來。一旦客戶端和服務(wù)器端建立起連接,就變成了一種全雙工的通信方式,誰來扮演服務(wù)器端或者客戶機(jī)端就顯得不那么重要了。
因此服務(wù)器的主要任務(wù)是一直偵聽是否客戶端的服務(wù)有連接請求并與實(shí)現(xiàn)與客戶端建立連接,這個(gè)由我們創(chuàng)建的特定目的的服務(wù)器對象來決定的。而客戶機(jī)端的任務(wù)就是需要服務(wù)器提供服務(wù)的時(shí)候,就發(fā)送服務(wù)請求給服務(wù)器,試著與能夠提供服務(wù)的服務(wù)器通過“三次握手”來建立連接,這是由我們創(chuàng)建的特定客戶機(jī)端的對象完成的。
一旦客戶機(jī)端和服務(wù)器端的連接建立好后,那么無論是在服務(wù)器端還是客戶機(jī)端,連接就只是變成了一個(gè)普通的IO數(shù)據(jù)流對象。從這時(shí)開始,我們可以象讀寫一個(gè)普通的文件那樣對待客戶機(jī)端和服務(wù)器端建立的連接。所以一旦客戶機(jī)端和服務(wù)器端建好連接后,我們只需使用自己熟悉的IO命令進(jìn)行操作即可。
圖2.2服務(wù)器和客戶端
上面已經(jīng)討論了Socket的原理[4,5],我們可以通過具體的案例,來了解Socket的工作方式。依據(jù)TCP/IP的協(xié)議,在C/S的架構(gòu)下的通訊過程中,客戶端和服務(wù)器端的Socket操作如下[6,7,8]:
(1)實(shí)例化Socket對象?;诜?wù)器端的端口號和IP地址來實(shí)例化Socket對象。
(2)客戶端連接服務(wù)器端。通過調(diào)用connect方法將客戶端連接到服務(wù)器上。
(3)填充I/O對象。調(diào)用BufferedReader、PrintWriter等方法把發(fā)送到服務(wù)器的I/O流填充到I/O對象里。
(4)給服務(wù)器端發(fā)送數(shù)據(jù)。利用I/O流對象及其Socket所提供的getInputStream和getOutputStream方法,向服務(wù)器端發(fā)送客戶端的數(shù)據(jù)流。
(5)斷開客戶端和服務(wù)器端的連接。服務(wù)請求完成之后,再關(guān)閉打開的I/O對象和Socket對象。
(1)實(shí)例化ServerSocket對象。在服務(wù)器端,首先使用一個(gè)端口來實(shí)例化一個(gè)ServerSocket對象。此時(shí),服務(wù)器就可以通過這個(gè)端口時(shí)時(shí)刻刻監(jiān)聽從客戶端發(fā)來的連接請求。
(2)監(jiān)聽客戶端請求。建立連接,通過調(diào)用ServerSocket的accept方法監(jiān)聽來自客戶端發(fā)送過來的連接請求。
(3)實(shí)現(xiàn)I/O操作。利用accept方法返回的客戶端的Socket對象,進(jìn)行讀寫I/O的操作。
(4)斷開客戶端和服務(wù)器端的連接。當(dāng)通訊完成后,關(guān)閉打開的流和Socket對象。
圖4.1 socket系統(tǒng)調(diào)用過程
上圖顯示了程序使用面向連接協(xié)議(tcp)時(shí),進(jìn)行的典型socket系統(tǒng)調(diào)用。服務(wù)器程序建立了一個(gè)socket,并調(diào)用bind函數(shù)將此socket和本地協(xié)議端口聯(lián)系起來,然后用listen和accept函數(shù)將此socket參數(shù)置于被動(dòng)的監(jiān)聽模式并接收到建立連接。
在一個(gè)對話系統(tǒng)中,server需要輪流查詢與各client建立的socket,一旦可讀就將該socket中的字符讀出來并向所有其他client發(fā)送。并且,server還要隨時(shí)查看是否有新的client試圖建立連接,這樣,如果server在任何一個(gè)地方阻塞了,其他client發(fā)送的內(nèi)容就會(huì)受到影響,得不到服務(wù)器的及時(shí)響應(yīng)。新client試圖建立連接也會(huì)受到影響。所以我們在這里不能使用缺省的阻塞的文件工作方式,而需要將文件的工作方式變成非阻塞方式。在UNIX下,函數(shù)fcntl()可以用來改變文件I/O操作的工作方式,函數(shù)描述如下:
由于判斷是否有新連接,是否可讀都是非阻塞的,因此每次判斷,不管有還是沒有,都會(huì)馬上返回.這樣,任何一個(gè)client向server發(fā)送字符或者試圖建立新連接,都不會(huì)對其他client的活動(dòng)造成影響。
對client而言,建立連接之后,只需要處理兩個(gè)文件描述符,一個(gè)是建立了連接的socket描述符,另一個(gè)是標(biāo)準(zhǔn)輸入.和server一樣,如果使用阻塞方式的話,很容易因?yàn)槠渲幸粋€(gè)暫時(shí)沒有輸入而影響另外一個(gè)的讀入,因此將它們都變成非阻塞的,然后client進(jìn)行如下動(dòng)作:
通過以上Socket對話系統(tǒng)的設(shè)計(jì),不管是 server還是client,它們都不停的輪流查詢各個(gè)文件描述符,一旦可讀就讀入并進(jìn)行處理。這樣的程序,不停的在執(zhí)行,只要有CPU資源,就不會(huì)放過。服務(wù)器端不停監(jiān)聽是否有客戶端發(fā)來請求連接信息,一旦發(fā)現(xiàn)就通過“三次握手”來建立連接,最后通過相應(yīng)的類提供的方法來實(shí)現(xiàn)相互通信。
[1]孫一林,彭波.Java網(wǎng)絡(luò)編程實(shí)例[M].清華大學(xué)出版社,2003.
[2]李樹青.Java通用范例開發(fā)金典 [M]. 電子工業(yè)出版社,2009
[3]王鵬.Java Swing圖形界面開發(fā)與案例詳解[M].清華大學(xué)出版社,2008
[4]龐永慶,翟鵬.Java完全自學(xué)寶典[M].清華大學(xué)出版社,2008
[5]劉永華,于春花.Java網(wǎng)絡(luò)編程 [M]. 清華大學(xué)出版社,2008
[6]李揚(yáng),耿昌宇,張麗芬等.基于Socket通訊模式下的跨平臺(tái)數(shù)據(jù)同步[J].北京理工大學(xué)學(xué)報(bào),2002,22(1):81-84.
[7]朱斌.LinuxSocket編程及其在無線網(wǎng)關(guān)中的應(yīng)用[J].微計(jì)算機(jī)信息,2007,23(3):70-71.
[8]谷巖.利用Java的Socket編程機(jī)制實(shí)現(xiàn)在線交談[J].計(jì)算機(jī)工程與設(shè)計(jì),2004,25(6):44-46.
Based on the UNIX Platforms Socket Dialogue System Design
SONGXiao-Li1,2,LI Hong1
(1.Cent ralSout h Uni versi t y,Changsha410083,H unan 2.H unan Indust ryPol yt echni c,Changsha410208,H unan)
Socketprogram m i ng i sused t o resol ve net work probl em ofi nt erprocesscom m uni cat i on.SocketInt erf ace provi desa new way t o com m unicat ewi t h each ot heri n t heprocess,SocketInt erf acenotonl ycan beused t ocom m uni cat ewi t h each ot heri n t hesam em achi ne,i nt ernalprocesses,butal sot o com m uni cat ewi t h each ot herbet ween t heInt ernetf unct i ons.Thi spaperdi scussand research on rel at ed t heori es,and on t hi sbasi st odesi gn adi al ogsyst em.
UNIX;SocketInt erf ace;Di al oguesyst em;TCP/IP
TP32
[文章編號]1671-5004(2012) 01-0020-03
2012-2-13
宋曉莉(1976-),女,湖南花垣人,湖南工業(yè)職業(yè)技術(shù)學(xué)院講師,中南大學(xué)軟件學(xué)院在讀碩士研究生,研究方向:軟件工程