計算機網(wǎng)絡(luò)是通過傳輸介質(zhì)、通信設(shè)施和網(wǎng)絡(luò)通信協(xié)議,把分散在不同地點的計算機設(shè)備互連起來,實現(xiàn)資源共享和數(shù)據(jù)傳輸?shù)南到y(tǒng)。網(wǎng)絡(luò)編程就就是編寫程序使聯(lián)網(wǎng)的兩個(或多個)設(shè)備(例如計算機)之間進行數(shù)據(jù)傳輸。 Java語言對網(wǎng)絡(luò)編程提供了良好的支持,通過其提供的接口我們可以很方便地進行網(wǎng)絡(luò)編程。下面先對網(wǎng)絡(luò)編程的一些基礎(chǔ)知識進行介紹,最后給出使用Java語言進行網(wǎng)絡(luò)編程的實例。
計算機網(wǎng)絡(luò)20世紀60年代出現(xiàn),經(jīng)歷了20世紀70年代、80年代和90年代的發(fā)展,進入21世紀后,計算機網(wǎng)絡(luò)已經(jīng)成為信息社會的基礎(chǔ)設(shè)施,深入到人類社會的方方面面,與人們的工作、學(xué)習(xí)和生活息息相關(guān)。
如同人與人之間相互交流是需要遵循一定的規(guī)矩一樣,計算機之間能夠進行相互通信是因為它們都共同遵守一定的規(guī)則,即網(wǎng)絡(luò)協(xié)議。
計算機網(wǎng)絡(luò)是個復(fù)雜的系統(tǒng),按照人們解決復(fù)雜問題的方法,把計算機網(wǎng)絡(luò)實現(xiàn)的功能分到不同的層次上,層與層之間用接口連接。通信的雙方具有相同的層次,層次實現(xiàn)的功能由協(xié)議數(shù)據(jù)單元(PDU)來描述。不同系統(tǒng)中的同一層構(gòu)成對等層,對等層之間通過對等層協(xié)議進行通信,理解彼此定義好的規(guī)則和約定。
計算機網(wǎng)絡(luò)體系結(jié)構(gòu)是計算機網(wǎng)絡(luò)層次和協(xié)議的集合,網(wǎng)絡(luò)體系結(jié)構(gòu)對計算機網(wǎng)絡(luò)實現(xiàn)的功能,以及網(wǎng)絡(luò)協(xié)議、層次、接口和服務(wù)進行了描述,但并不涉及具體的實現(xiàn)。接口是同一節(jié)點內(nèi)相鄰層之間交換信息的連接處,也叫服務(wù)訪問點(SAP)。
計算機網(wǎng)絡(luò)層次模型
前面我們介紹了計算機網(wǎng)絡(luò)的體系結(jié)構(gòu),因為計算機網(wǎng)絡(luò)是個復(fù)雜的系統(tǒng),所以把計算機網(wǎng)絡(luò)實現(xiàn)的功能分到不同的層次上,而計算機網(wǎng)絡(luò)體系結(jié)構(gòu)是計算機網(wǎng)絡(luò)層次和協(xié)議的集合。那么,計算機網(wǎng)絡(luò)如何進行分層呢?下面先介紹的是OSI參考模型。
世界上第一個網(wǎng)絡(luò)體系結(jié)構(gòu)由IBM公司提出(1974年,SNA),以后其他公司也相繼提出自己的網(wǎng)絡(luò)體系結(jié)構(gòu)如:Digital公司的DNA,美國國防部的TCP/IP等,多種網(wǎng)絡(luò)體系結(jié)構(gòu)并存,其結(jié)果是若采用IBM的結(jié)構(gòu),只能選用IBM的產(chǎn)品,只能與同種結(jié)構(gòu)的網(wǎng)絡(luò)互聯(lián)。
為了促進計算機網(wǎng)絡(luò)的發(fā)展,國際標準化組織ISO于1977年成立了一個委員會,在現(xiàn)有網(wǎng)絡(luò)的基礎(chǔ)上,提出了不基于具體機型、操作系統(tǒng)或公司的網(wǎng)絡(luò)體系結(jié)構(gòu),稱為開放系統(tǒng)互連參考模型,即OSI/RM (Open System Interconnection Reference Model)。OSI模型把網(wǎng)絡(luò)通信的工作分為7層,分別是物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會話層、表示層和應(yīng)用層。
OSI參考模型的7個層次
物理層
物理層處于OSI的最底層,是整個開放系統(tǒng)的基礎(chǔ)。物理層涉及通信信道上傳輸?shù)脑急忍亓?bits),它的功能主要是為數(shù)據(jù)端設(shè)備提供傳送數(shù)據(jù)的通路以及傳輸數(shù)據(jù)。
數(shù)據(jù)鏈路層
數(shù)據(jù)鏈路層的主要任務(wù)是實現(xiàn)計算機網(wǎng)絡(luò)中相鄰節(jié)點之間的可靠傳輸,把原始的、有差錯的物理傳輸線路加上數(shù)據(jù)鏈路協(xié)議以后,構(gòu)成邏輯上可靠的數(shù)據(jù)鏈路。需要完成的功能有鏈路管理、成幀、差錯控制以及流量控制等。其中成幀是對物理層的原始比特流進行界定,數(shù)據(jù)鏈路層也能夠?qū)膩G失進行處理。
網(wǎng)絡(luò)層
網(wǎng)絡(luò)層涉及源主機節(jié)點到目的主機節(jié)點之間可靠的網(wǎng)絡(luò)傳輸,它需要完成的功能主要包括路由選擇、網(wǎng)絡(luò)尋址、流量控制、擁塞控制、網(wǎng)絡(luò)互連等。
傳輸層
傳輸層起著承上啟下的作用,涉及源端節(jié)點到目的端節(jié)點之間可靠的信息傳輸。傳輸層需要解決跨越網(wǎng)絡(luò)連接的建立和釋放,對底層不可靠的網(wǎng)絡(luò),建立連接時需要三次握手,釋放連接時需要四次揮手。
會話層和表示層
會話層的主要功能是負責應(yīng)用程序之間建立、維持和中斷會話,同時也提供對設(shè)備和結(jié)點之間的會話控制,協(xié)調(diào)系統(tǒng)和服務(wù)之間的交流,并通過提供單工、半雙工和全雙工3種不同的通信方式,使系統(tǒng)和服務(wù)之間有序地進行通信。
表示層關(guān)心所傳輸數(shù)據(jù)信息的格式定義,其主要功能是把應(yīng)用層提供的信息變換為能夠共同理解的形式,提供字符代碼、數(shù)據(jù)格式、控制信息格式、加密等的統(tǒng)一表示。
應(yīng)用層
應(yīng)用層為OSI的最高層,是直接為應(yīng)用進程提供服務(wù)的。其作用是在實現(xiàn)多個系統(tǒng)應(yīng)用進程相互通信的同時,完成一系列業(yè)務(wù)處理所需的服務(wù)。
OSI參考模型的初衷是提供全世界范圍的計算機網(wǎng)絡(luò)都要遵循的統(tǒng)一標準,但是由于存在模型和協(xié)議自身的缺陷,遲遲沒有成熟的產(chǎn)品推出。TCP/IP協(xié)議在實踐中不斷完善和發(fā)展取得成功,作為網(wǎng)絡(luò)的基礎(chǔ),Internet的語言,可以說沒有TCP/IP協(xié)議就沒有互聯(lián)網(wǎng)的今天。
TCP/IP,即Transmission Control Protocol/Internet Protocol的簡寫,中譯名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議,是Internet最基本的協(xié)議、Internet國際互聯(lián)網(wǎng)絡(luò)的基礎(chǔ)。
TCP/IP協(xié)議是一個開放的網(wǎng)絡(luò)協(xié)議簇,它的名字主要取自最重要的網(wǎng)絡(luò)層IP協(xié)議和傳輸層TCP協(xié)議。TCP/IP協(xié)議定義了電子設(shè)備如何連入因特網(wǎng),以及數(shù)據(jù)如何在它們之間傳輸?shù)臉藴?。TCP/IP參考模型采用4層的層級結(jié)構(gòu),每一層都呼叫它的下一層所提供的協(xié)議來完成自己的需求,這4個層次分別是:網(wǎng)絡(luò)接口層、互聯(lián)網(wǎng)層(IP層)、傳輸層(TCP層)、應(yīng)用層。
OSI 和 TCP/IP模型對比
網(wǎng)絡(luò)接口層
TCP/IP協(xié)議對網(wǎng)絡(luò)接口層沒有給出具體的描述,網(wǎng)絡(luò)接口層對應(yīng)著物理層和數(shù)據(jù)鏈路層。
互聯(lián)網(wǎng)層 ( IP層 )
互聯(lián)網(wǎng)層是整個TCP/IP協(xié)議棧的核心。它的功能是把分組發(fā)往目標網(wǎng)絡(luò)或主機。同時,為了盡快地發(fā)送分組,可能需要沿不同的路徑同時進行分組傳遞。因此,分組到達的順序和發(fā)送的順序可能不同,這就需要上層必須對分組進行排序。互聯(lián)網(wǎng)層除了需要完成路由的功能外,也可以完成將不同類型的網(wǎng)絡(luò)(異構(gòu)網(wǎng))互連的任務(wù)。除此之外,互聯(lián)網(wǎng)層還需要完成擁塞控制的功能?! ?/p>
傳輸層 ( TCP層 )
TCP層負責在應(yīng)用進程之間建立端到端的連接和可靠通信,它只存在與端節(jié)點中。TCP層涉及兩個協(xié)議,TCP和UDP。其中,TCP協(xié)議提供面向連接的服務(wù),提供按字節(jié)流的有序、可靠傳輸,可以實現(xiàn)連接管理、差錯控制、流量控制、擁塞控制等。UDP協(xié)議提供無連接的服務(wù),用于不需要或無法實現(xiàn)面向連接的網(wǎng)絡(luò)應(yīng)用中。
應(yīng)用層
應(yīng)用層為Internet中的各種網(wǎng)絡(luò)應(yīng)用提供服務(wù)。
上面主要介紹了OSI參考模型和TCP/IP模型的相關(guān)內(nèi)容,從下面這張圖可以看出TCP/IP協(xié)議簇中不同的層次中有著很多不同的網(wǎng)絡(luò)協(xié)議,下面主要介紹傳輸層的TCP、UDP協(xié)議和應(yīng)用層的HTTP協(xié)議
簡介
TCP(Transmission Control Protocol ,傳輸控制協(xié)議)是面向連接的傳輸層協(xié)議。TCP層是位于IP層之上,應(yīng)用層之下的中間層。不同主機的應(yīng)用層之間經(jīng)常需要可靠的、像管道一樣的連接,但是IP層不提供這樣的流機制,而是提供不可靠的包交換。TCP協(xié)議采用字節(jié)流傳輸數(shù)據(jù)。
TCP報文段格式
TCP報文段包括協(xié)議首部和數(shù)據(jù)兩部分,協(xié)議首部的固定部分有20個字節(jié),首部的固定部分后面是選項部分。
TCP報文段
下面是報文段首部各個字段的含義。
源端口號以及目的端口號,各占2個字節(jié),端口是傳輸層和應(yīng)用層的服務(wù)接口,用于尋找發(fā)送端和接收端的進程,一般來講,通過端口號和IP地址,可以唯一確定一個TCP連接,在網(wǎng)絡(luò)編程中,通常被稱為一個socket接口。
序號,占4字節(jié),用來標識從TCP發(fā)送端向TCP接收端發(fā)送的數(shù)據(jù)字節(jié)流。
確認序號,占4字節(jié),包含發(fā)送確認的一端所期望收到的下一個序號,因此,確認序號應(yīng)該是上次已經(jīng)成功收到數(shù)據(jù)字節(jié)序號加1.
數(shù)據(jù)偏移,占4位,用于指出TCP首部長度,若不存在選項,則這個值為20字節(jié),數(shù)據(jù)偏移的最大值為60字節(jié)。
保留字段占6位,暫時可忽略,值全為0
標志位
URG(緊急) : 為1時表明緊急指針字段有效
ACK(確認):為1時表明確認號字段有效
PSH(推送):為1時接收方應(yīng)盡快將這個報文段交給應(yīng)用層
RST(復(fù)位):為1時表明TCP連接出現(xiàn)故障必須重建連接
SYN(同步):在連接建立時用來同步序號
FIN (終止): 為1時表明發(fā)送端數(shù)據(jù)發(fā)送完畢要求釋放連接
接收窗口占2個字節(jié),用于流量控制和擁塞控制,表示當前接收緩沖區(qū)的大小。在計算機網(wǎng)絡(luò)中,通常是用接收方的接收能力的大小來控制發(fā)送方的數(shù)據(jù)發(fā)送量。TCP連接的一端根據(jù)緩沖區(qū)大小確定自己的接收窗口值,告訴對方,使對方可以確定發(fā)送數(shù)據(jù)的字節(jié)數(shù)。
校驗和占2個字節(jié),范圍包括首部和數(shù)據(jù)兩部分。
選項是可選的,默認情況是不選
三次握手與四次揮手
TCP是面向連接的協(xié)議,因此每個TCP連接都有3個階段:連接建立、數(shù)據(jù)傳送和連接釋放。連接建立經(jīng)歷三個步驟,通常稱為“三次握手”。
TCP三次握手過程如下:
TCP三次握手.jpg
1、第一次握手
客戶機發(fā)送連接請求報文段到服務(wù)器,并進入SYN_SENT狀態(tài),等待服務(wù)器確認。(SYN = 1,seq=x)
2、第二次握手
服務(wù)器收到連接請求報文,如果同意建立連接,向客戶機發(fā)回確認報文段,并為該TCP連接分配TCP緩存和變量。(SYN=1,ACK=1,seq=y,ack=x 1)。
3、第三次握手
客戶機收到服務(wù)器的確認報文段后,向服務(wù)器給出確認報文段,并且也要給該連接分配緩存和變量。此包發(fā)送完畢,客戶端和服務(wù)器進入ESTABLISHED(TCP連接成功)狀態(tài),完成三次握手。(ACK=1,seq=x 1,ack=y 1)。
TCP四次揮手過程如下:
TCP四次揮手過程如下:
四次揮手.png
由于TCP連接是全雙工的,因此每個方向都必須單獨進行關(guān)閉。這原則是當一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數(shù)據(jù)流動,一個TCP連接在收到一個FIN后仍能發(fā)送數(shù)據(jù)。首先進行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方執(zhí)行被動關(guān)閉。
1、TCP客戶端發(fā)送一個FIN,用來關(guān)閉客戶到服務(wù)器的數(shù)據(jù)傳送。
2、’服務(wù)器收到這個FIN,它發(fā)回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將占用一個序號。
3、服務(wù)器關(guān)閉客戶端的連接,發(fā)送一個FIN給客戶端。
4、客戶端發(fā)回ACK報文確認,并將確認序號設(shè)置為收到序號加1。
簡介
UDP,用戶數(shù)據(jù)報協(xié)議,英文全稱是User Datagram Protocol,它是TCP/IP協(xié)議簇中無連接的運輸層協(xié)議。
UDP協(xié)議格式
UDP格式
從圖中可以看到,UDP協(xié)議十分簡單,它由兩部分組成:首部和數(shù)據(jù)。其中,首部僅有8個字節(jié),包括源端口和目的端口,長度(UDP用于數(shù)據(jù)報的長度)、校驗和。
簡介
HTTP,超文本傳輸協(xié)議,英文全稱是Hypertext Transfer Protocol,它是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議。HTTP是一種應(yīng)用層協(xié)議,它是基于TCP協(xié)議之上的請求/響應(yīng)式的協(xié)議,即一個客戶端與服務(wù)器建立連接后,向服務(wù)器發(fā)送一個請求;服務(wù)器接到請求后,給予相應(yīng)的響應(yīng)信息。HTTP協(xié)議默認的端口號為80.
現(xiàn)在使用的HTTP協(xié)議是HTTP/1.1版本,1997年之前采用的是HTTP1.0版本。HTTP連接在1.0版本中采用非持續(xù)連接工作方式,1.1版本采用的是持續(xù)連接工作方式,持續(xù)連接是指服務(wù)器在發(fā)送響應(yīng)后仍然在一段時間內(nèi)保持這條由TCP運輸層協(xié)議建立起來的連接,使客戶機和服務(wù)器可以繼續(xù)在這條連接上傳輸HTTP報文。
是否采用持續(xù)連接工作方式,1.0中默認是關(guān)閉的,需要在HTTP頭加入"Connection:Keep-Alive",才能啟用Keep-Alive。HTTP1.1中默認啟用Keep-Alive,如果加入"Connection:close",才關(guān)閉。目前大部分瀏覽器都是用HTTP1.1協(xié)議,也就是說默認都會發(fā)起Keep-Alive的連接請求了,所以是否能完成一個完整的Keep- Alive連接就看服務(wù)器設(shè)置情況。
HTTP報文
HTTP協(xié)議是基于TCP協(xié)議之上的請求/響應(yīng)式協(xié)議,下面主要介紹HTTP報文的格式,HTTP報文主要有請求報文和響應(yīng)報文兩種。首先看請求報文的格式:
HTTP請求報文格式
HTTP請求報文由請求行、首部行和實體主體組成,由瀏覽器發(fā)送給服務(wù)器。上面這張圖中SP表示空格,cr lf表示回車和換行。
HTTP響應(yīng)報文格式
上面這張圖是HTTP響應(yīng)報文,它由狀態(tài)行、首部行和實體主體組成。下面兩張圖是在谷歌瀏覽器內(nèi)訪問服務(wù)器查看的HTTP請求和響應(yīng)。
HTTP請求報文例子
HTTP響應(yīng)報文例子
HTTP請求方法和響應(yīng)狀態(tài)碼
在上面的HTTP請求報文例子中,我們可以看到請求方法是GET,這表示請求讀取由URL所標志的信息,除了GET,還有其它幾種常用的方法。
HTTP請求報文的一些方法
在HTTP響應(yīng)報文的例子中,我們可以看到狀態(tài)碼是200,表示響應(yīng)成功。下表是其它狀態(tài)碼,總共5大類,33種。
HTTP響應(yīng)報文的狀態(tài)碼
1、HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎(chǔ)是SSL,因此加密的詳細內(nèi)容就需要SSL。它是一個URI scheme(抽象標識符體系),句法類同http:體系。用于安全的HTTP數(shù)據(jù)傳輸。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默認端口及一個加密/身份驗證層(在HTTP與TCP之間)。
2、超文本傳輸協(xié)議HTTP協(xié)議被用于在Web瀏覽器和網(wǎng)站服務(wù)器之間傳遞信息。HTTP協(xié)議以明文方式發(fā)送內(nèi)容,不提供任何方式的數(shù)據(jù)加密,如果攻擊者截取了Web瀏覽器和網(wǎng)站服務(wù)器之間的傳輸報文,就可以直接讀懂其中的信息,因此HTTP協(xié)議不適合傳輸一些敏感信息,比如信用卡號、密碼等。
3、為了解決HTTP協(xié)議的這一缺陷,需要使用另一種協(xié)議:安全套接字層超文本傳輸協(xié)議HTTPS。為了數(shù)據(jù)傳輸?shù)陌踩琀TTPS在HTTP的基礎(chǔ)上加入了SSL協(xié)議,SSL依靠證書來驗證服務(wù)器的身份,并為瀏覽器和服務(wù)器之間的通信加密。
4、HTTPS和HTTP的區(qū)別主要為以下四點:1、https協(xié)議需要到ca申請證書,一般免費證書很少,需要交費。2、http是超文本傳輸協(xié)議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協(xié)議。3、http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。4、http的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL HTTP協(xié)議構(gòu)建的可進行加密傳輸、身份認證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。
到這里,關(guān)于計算機網(wǎng)絡(luò)部分的總結(jié)內(nèi)容就結(jié)束了,下面是幾個常見的問題,匯總在這里。
OSI,開放系統(tǒng)互連參考模型,它的7個層次自頂?shù)较乱来螢閼?yīng)用層,表示層,會話層,傳輸層,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層和物理層。各層的功能見文章開始。
TCP協(xié)議是傳輸控制協(xié)議,UDP協(xié)議是用戶數(shù)據(jù)報協(xié)議,兩者都是傳輸層的協(xié)議,主要區(qū)別在于前者是可靠的,面向連接的協(xié)議,后者是不可靠的,無連接的協(xié)議。其它的區(qū)別還有,TCP協(xié)議傳輸速度慢,UDP常用于一次性傳輸比較少量數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用。
主要是防止兩次握手情況下已經(jīng)失效的連接請求報文段突然又傳送到服務(wù)端而產(chǎn)生錯誤。例如,客戶機A向服務(wù)器B發(fā)送TCP連接請求,第一個連接請求報文在網(wǎng)絡(luò)的某個節(jié)點長時間滯留,A超時后認為報文丟失,于是再重傳一次連接請求,B收到后建立連接。數(shù)據(jù)傳輸完畢后雙方斷開連接,而這時之前滯留的連接請求到達了服務(wù)端B,而B認為A又發(fā)來連接請求。如果兩次握手建立連接,A并無連接請求,造成B的資源浪費。
GET和POST是HTTP請求的兩種方法,主要區(qū)別在于GET方法是請求讀取由URL所標志的信息,POST是給服務(wù)器添加信息。點擊查看更多
(1) 輸出包含域名的網(wǎng)址 (2) 瀏覽器向DNS請求解析域名對應(yīng)的IP地址 (3) 域名系統(tǒng)DNS解析出域名對應(yīng)的IP地址 (4) 瀏覽器與該服務(wù)器建立TCP連接 (5) 瀏覽器發(fā)送HTTP請求 (6) 服務(wù)器通過HTTP響應(yīng)把頁面文件發(fā)送給瀏覽器 (7) TCP連接釋放 (8) 瀏覽器解釋文件,并顯示
Java的網(wǎng)絡(luò)編程主要涉及到的內(nèi)容是Socket編程,那么什么是Socket呢?簡單地說,Socket,套接字,就是兩臺主機之間邏輯連接的端點。TPC/IP協(xié)議是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸,而HTTP是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。Socket,本質(zhì)上就是一組接口,是對TCP/IP協(xié)議的封裝和應(yīng)用(程序員層面上)。
Socket編程主要涉及到客戶端和服務(wù)器端兩個方面,首先是在服務(wù)器端創(chuàng)建一個服務(wù)器套接字(ServerSocket),并把它附加到一個端口上,服務(wù)器從這個端口監(jiān)聽連接。端口號的范圍是0到65536,但是0到1024是為特權(quán)服務(wù)保留的端口號,我們可以選擇任意一個當前沒有被其他進程使用的端口。
客戶端請求與服務(wù)器進行連接的時候,根據(jù)服務(wù)器的域名或者IP地址,加上端口號,打開一個套接字。當服務(wù)器接受連接后,服務(wù)器和客戶端之間的通信就像輸入輸出流一樣進行操作。
下面是一個客戶端和服務(wù)器端進行數(shù)據(jù)交互的簡單例子,客戶端輸入正方形的邊長,服務(wù)器端接收到后計算面積并返回給客戶端,通過這個例子可以初步對Socket編程有個把握。
服務(wù)器端
1 public class SocketServer { 2 3 public static void main(String[] args) throws IOException { 4 5 // 端口號 6 int port = 7000; 7 // 在端口上創(chuàng)建一個服務(wù)器套接字 8 ServerSocket serverSocket = new ServerSocket(port); 9 // 監(jiān)聽來自客戶端的連接10 Socket socket = serverSocket.accept();11 12 DataInputStream dis = new DataInputStream(13 new BufferedInputStream(socket.getInputStream()));14 15 DataOutputStream dos = new DataOutputStream(16 new BufferedOutputStream(socket.getOutputStream()));17 18 do {19 20 double length = dis.readDouble();21 System.out.println("服務(wù)器端收到的邊長數(shù)據(jù)為:" length);22 double result = length * length;23 dos.writeDouble(result);24 dos.flush();25 26 } while (dis.readInt() != 0);27 28 socket.close();29 serverSocket.close();30 }31 }
客戶端
1 public class SocketClient { 2 3 public static void main(String[] args) throws UnknownHostException, IOException { 4 5 int port = 7000; 6 7 String host = "localhost"; 8 9 // 創(chuàng)建一個套接字并將其連接到指定端口號10 Socket socket = new Socket(host, port);11 12 DataInputStream dis = new DataInputStream(13 new BufferedInputStream(socket.getInputStream()));14 15 DataOutputStream dos = new DataOutputStream(16 new BufferedOutputStream(socket.getOutputStream()));17 18 Scanner sc = new Scanner(System.in);19 20 boolean flag = false;21 22 while (!flag) {23 24 System.out.println("請輸入正方形的邊長:");25 double length = sc.nextDouble();26 27 dos.writeDouble(length);28 dos.flush();29 30 double area = dis.readDouble();31 32 System.out.println("服務(wù)器返回的計算面積為:" area);33 34 while (true) {35 36 System.out.println("繼續(xù)計算?(Y/N)");37 38 String str = sc.next();39 40 if (str.equalsIgnoreCase("N")) {41 dos.writeInt(0);42 dos.flush();43 flag = true;44 break;45 } else if (str.equalsIgnoreCase("Y")) {46 dos.writeInt(1);47 dos.flush();48 break;49 }50 }51 }52 53 socket.close();54 }55 }
可以看到上面的服務(wù)器端程序和客戶端程序是一對一的關(guān)系,為了能讓一個服務(wù)器端程序能同時為多個客戶提供服務(wù),可以使用多線程機制,每個客戶端的請求都由一個獨立的線程進行處理。下面是改寫后的服務(wù)器端程序。
1 public class SocketServerM { 2 3 public static void main(String[] args) throws IOException { 4 5 int port = 7000; 6 int clientNo = 1; 7 8 ServerSocket serverSocket = new ServerSocket(port); 9 10 // 創(chuàng)建線程池11 ExecutorService exec = Executors.newCachedThreadPool();12 13 try {14 15 while (true) {16 Socket socket = serverSocket.accept();17 exec.execute(new SingleServer(socket, clientNo));18 clientNo ;19 }20 21 } finally {22 serverSocket.close();23 }24 25 }26 }27 28 class SingleServer implements Runnable {29 30 private Socket socket;31 private int clientNo;32 33 public SingleServer(Socket socket, int clientNo) {34 this.socket = socket;35 this.clientNo = clientNo;36 }37 38 @Override39 public void run() {40 41 try {42 43 DataInputStream dis = new DataInputStream(44 new BufferedInputStream(socket.getInputStream()));45 46 DataOutputStream dos = new DataOutputStream(47 new BufferedOutputStream(socket.getOutputStream()));48 49 do {50 51 double length = dis.readDouble();52 System.out.println("從客戶端" clientNo "接收到的邊長數(shù)據(jù)為:" length);53 double result = length * length;54 dos.writeDouble(result);55 dos.flush();56 57 } while (dis.readInt() != 0);58 59 } catch (IOException e) {60 e.printStackTrace();61 } finally {62 System.out.println("與客戶端" clientNo "通信結(jié)束");63 try {64 socket.close();65 } catch (IOException e) {66 e.printStackTrace();67 }68 }69 }70 }
上面改進后的服務(wù)器端代碼可以支持不斷地并發(fā)響應(yīng)網(wǎng)絡(luò)中的客戶請求。關(guān)鍵的地方在于多線程機制的運用,同時利用線程池可以改善服務(wù)器程序的性能。
聯(lián)系客服