面向?qū)ο蟮某绦蛟O(shè)計(jì)Java第三版第15章課件_第1頁(yè)
面向?qū)ο蟮某绦蛟O(shè)計(jì)Java第三版第15章課件_第2頁(yè)
面向?qū)ο蟮某绦蛟O(shè)計(jì)Java第三版第15章課件_第3頁(yè)
面向?qū)ο蟮某绦蛟O(shè)計(jì)Java第三版第15章課件_第4頁(yè)
面向?qū)ο蟮某绦蛟O(shè)計(jì)Java第三版第15章課件_第5頁(yè)
已閱讀5頁(yè),還剩66頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第15章 網(wǎng)絡(luò)編程 15.1 URL通信 15.2 Socket通信 15.3 UDP通信 15.1 URL通信URL(Uniform Resource Locator,統(tǒng)一資源定位器)表示Internet/Intranet上的資源位置。這些資源可以是一個(gè)文件、一個(gè)目錄或一個(gè)對(duì)象。當(dāng)我們使用瀏覽器瀏覽網(wǎng)絡(luò)上的資源時(shí),首先需要鍵入U(xiǎn)RL地址,才可以訪問(wèn)相應(yīng)的主頁(yè)。例如::80/index.htmlhttp:/index.htmlfile:/c:/ABC/xx.java每個(gè)完整的URL由四部分組成,這四部分的劃分及其含義如表15.1中所示。表15.1 URL地址的組成 一般的通信協(xié)議都已經(jīng)規(guī)定好了

2、開(kāi)始聯(lián)絡(luò)時(shí)的通信端口,例如,HTTP協(xié)議的缺省端口號(hào)是80,F(xiàn)TP協(xié)議的缺省端口號(hào)是21等。URL使用協(xié)議的缺省端口號(hào)時(shí),可以不寫出缺省端口號(hào)。所以,一般的URL地址只包含傳輸協(xié)議、主機(jī)名和文件名就足夠了。網(wǎng)絡(luò)通信中,我們常常會(huì)碰到地址(Address)和端口(Port)的問(wèn)題。兩個(gè)程序之間只有在地址和端口方面都達(dá)成一致時(shí),才能建立連接。這與我們寄信要有地址、打電話要有電話號(hào)碼一樣。兩個(gè)遠(yuǎn)方程序建立連接時(shí),首先需要知道對(duì)方的地址或主機(jī)名,其次是端口號(hào)。地址主要用來(lái)區(qū)分計(jì)算機(jī)網(wǎng)絡(luò)中的各個(gè)計(jì)算機(jī),而端口的定義可以理解為擴(kuò)展的號(hào)碼,具備一個(gè)地址的計(jì)算機(jī)可以通過(guò)不同的端口來(lái)與其他計(jì)算機(jī)進(jìn)行通信。在TC

3、P協(xié)議中,端口被規(guī)定為一個(gè)在065535之間的16位的整數(shù)。其中,01023被預(yù)先定義的服務(wù)通信占用(如FTP協(xié)議的端口號(hào)是21,HTTP協(xié)議的端口號(hào)為80等)。除非我們需要訪問(wèn)這些特定服務(wù),否則就應(yīng)該使用102465535這些端口中的某一個(gè)來(lái)進(jìn)行通信,以免發(fā)生端口的沖突。15.1.1 URL類要使用URL進(jìn)行網(wǎng)絡(luò)編程,就必須創(chuàng)建URL對(duì)象。創(chuàng)建URL對(duì)象要使用軟件包中提供的.URL類的構(gòu)造方法。1創(chuàng)建URL對(duì)象URL類提供的用于創(chuàng)建URL對(duì)象的構(gòu)造方法有4個(gè):(1) URL(String spec)方法。根據(jù) String 表示形式創(chuàng)建URL對(duì)象。例如:URL file=new URL(/i

4、ndex.html);這種以完整的URL創(chuàng)建的URL對(duì)象稱為絕對(duì)URL,該對(duì)象包含了訪問(wèn)該URL所需要的全部信息。(2) URL(String protocol,String host,String file)方法。根據(jù)指定的protocol、host、port號(hào)和file創(chuàng)建URL對(duì)象。其中的protocol為協(xié)議名,host為主機(jī)名,file為文件名,端口號(hào)使用缺省值。例如:http,index.html(3) URL(String protocol,String host,String port,String file)方法。這個(gè)構(gòu)造方法與構(gòu)造方法(2)相比,增加了1個(gè)指定端口號(hào)的參數(shù)。

5、(4) URL(URL context,String spec)方法。通過(guò)在指定的上下文中用指定的處理程序?qū)o定的spec進(jìn)行解析來(lái)創(chuàng)建URL。例如:URL base=new URL(file: /c:/ABC/xx.java);URL gk=new URL(base,gg.txt);中的URL對(duì)象gk是相對(duì)URL對(duì)象。javac在使用對(duì)象gk時(shí)會(huì)從對(duì)象base中查出文件gg.txt所在的位置:本地主機(jī)是c:/ABC/。對(duì)象gk指明的資源也就是file: /c:/ABC/gg.txt。如果在程序中不訪問(wèn)xx.java,那么在創(chuàng)建base的構(gòu)造方法中則略去xx.java。創(chuàng)建gg的方法不變,gg

6、指明的資源仍不變。2URL類的常用成員方法創(chuàng)建URL對(duì)象后,可以使用.URL類的成員方法對(duì)創(chuàng)建的對(duì)象進(jìn)行處理。.URL的常用成員方法如表15.2所示。表15.2 URL類的常用成員方法15.1.2 利用URL類訪問(wèn)網(wǎng)上資源示例程序【示例程序C15_1.java】 獲取某個(gè)URL地址的協(xié)議名、主機(jī)名、端口號(hào)和文件名。package ch15;import .MalformedURLException;import .URL;public class C15_1 public static void main(String args ) URL MyURL=null; try MyURL=new

7、URL(/kb/docs/java/quickstart.html); catch (MalformedURLException e) System.out.println(MalformedURLException: + e); System.out.println(URL String: +MyURL.toString( ); /獲取URL對(duì)象轉(zhuǎn)換成字符串 System.out.println(Protocol: +MyURL.getProtocol( ); /獲取協(xié)議名 System.out.println(“Host: ”+MyURL.getHost( ); /獲取主機(jī)名 System

8、.out.println(“Port: ”+MyURL.getPort( ); /獲取端口號(hào) System.out.println(“File: ”+MyURL.getFile( ); /獲取文件名 該程序的運(yùn)行結(jié)果如圖15.1右下窗口所示。圖15.1 程序C15_1的運(yùn)行結(jié)果 【示例程序C15_2.java】 使用URL類的openStream()成員方法獲取URL指定的網(wǎng)上信息。package ch15;import java.io.*;import .MalformedURLException;import .URL;public class C15_2 public static vo

9、id main(String args) String Str; InputStream st1; /String ur=http:/kb/docs/java/quickstart.html; /獲取遠(yuǎn)程網(wǎng)上的信息 String ur=file:/E:/Java/ch15/src/ch15/C15_1.java; /獲取本地網(wǎng)上的信息 try URL MyURL=new URL(ur); st1=MyURL.openStream(); InputStreamReader ins=new InputStreamReader(st1); BufferedReader in=new Buffered

10、Reader(ins); while(Str=in.readLine()!= null) /從URL處獲取信息并顯示 System.out.println(Str); catch(MalformedURLException e) /創(chuàng)建URL對(duì)象可能產(chǎn)生的異常 System.out.println(Cant get URL: ); catch (IOException e) System.out.println(Error in I/O: + e.getMessage(); 由于URL的openStream()成員方法返回的是InputStream類的對(duì)象,因此只能通過(guò)read()方法逐個(gè)字節(jié)

11、地去讀URL地址處的資源信息。這里利用BufferedReader對(duì)原始信息流進(jìn)行了包裝和處理,以提高I/O效率。運(yùn)行的結(jié)果是顯示出C15_1.java程序的內(nèi)容。15.1.3 使用URLConnection類訪問(wèn)網(wǎng)上資源上面介紹的方法只能讀取遠(yuǎn)程計(jì)算機(jī)節(jié)點(diǎn)的信息,如果希望在讀取遠(yuǎn)程計(jì)算機(jī)節(jié)點(diǎn)的信息時(shí)還可向它寫入信息,則需要使用軟件包中的另一個(gè)類URLConnection。1創(chuàng)建URLConnection類的對(duì)象要?jiǎng)?chuàng)建URLConnection對(duì)象必須先創(chuàng)建一個(gè)URL對(duì)象,然后調(diào)用該對(duì)象的openConnection()方法就可以返回一個(gè)對(duì)應(yīng)其URL地址的URLConnection對(duì)象。例如:

12、URL MyURL=new URL(/index.html);URLConnection con= MyURL.openConnection();2建立輸入/輸出數(shù)據(jù)流讀取或?qū)懭脒h(yuǎn)程計(jì)算機(jī)節(jié)點(diǎn)的信息時(shí),要建立輸入或輸出數(shù)據(jù)流。我們可以利用URLConnection類的成員方法getInputStream()和getOutputStream()來(lái)獲取輸入和輸出數(shù)據(jù)流。例如,下面的兩行語(yǔ)句用于建立輸入數(shù)據(jù)流:InputStreamReader ins=new InputStreamReader(con.getInputStream();BufferedReader in=new BufferedR

13、eader(ins);下面的語(yǔ)句行用于建立輸出數(shù)據(jù)流:PrintStream out=new PrintStream(con.getOutputStream();3讀取遠(yuǎn)程計(jì)算機(jī)節(jié)點(diǎn)的信息或向其寫入信息要讀取遠(yuǎn)程計(jì)算機(jī)節(jié)點(diǎn)的信息,可調(diào)用in.readLine()方法;向遠(yuǎn)程計(jì)算機(jī)節(jié)點(diǎn)寫入信息時(shí),可調(diào)用out.println(參數(shù))方法。URLConnection類是一個(gè)抽象類,它是代表程序與URL對(duì)象之間建立通信連接的所有類的超類,此類的一個(gè)實(shí)例可以用來(lái)讀/寫URL對(duì)象所代表的資源。出于安全性的考慮,Java程序只能對(duì)特定的URL進(jìn)行寫操作,這種URL就是服務(wù)器上的CGI(Common Gat

14、eway Interface,公共網(wǎng)關(guān)接口)程序。CGI是客戶端瀏覽器與服務(wù)器進(jìn)行通信的接口。下面通過(guò)一個(gè)例子來(lái)說(shuō)明URLConnection類是如何使用的?!臼纠绦駽15_3.java】 使用URLConnection類從遠(yuǎn)程主機(jī)獲取信息。package ch15;import java.io.*;import .*;class C15_3 public static void main(String args) try String ur=“http:/”; /獲取遠(yuǎn)程網(wǎng)上的信息 / String ur=file:/E:/Java/ch15/src/ch15/C15_1.java ; /

15、獲取本地網(wǎng)上的信息 URL MyURL=new URL(ur); String str; URLConnection con=MyURL.openConnection(); InputStreamReader ins=new InputStreamReader(con.getInputStream(); BufferedReader in=new BufferedReader(ins); while (str=in.readLine()!=null) System.out.println(str); in.close(); catch (MalformedURLException mfURLe

16、) System.out.println(MalformedURLException: + mfURLe); catch (IOException ioe) System.out.println(“IOException: ” + ioe); 該程序的運(yùn)行結(jié)果如圖15.2所示。圖15.2 程序C15_3的運(yùn)行結(jié)果 15.2 Socket通信Socket套接字是應(yīng)用于網(wǎng)絡(luò)通信中的重要機(jī)制。Socket最初是加利福尼亞大學(xué)Berkeley分校為UNIX操作系統(tǒng)開(kāi)發(fā)的網(wǎng)絡(luò)通信接口。隨著UNIX操作系統(tǒng)的廣泛使用,套接字成為當(dāng)前最流行的網(wǎng)絡(luò)通信應(yīng)用程序接口之一。Java語(yǔ)言中采用的Socket通信是一

17、種流式套接字通信,它采用TCP協(xié)議,通過(guò)提供面向連接的服務(wù),實(shí)現(xiàn)客戶/服務(wù)器之間雙向、可靠的通信。包中的Socket類與ServerSocket類為流式套接字通信方式提供了充分的支持。15.2.1 Socket的概念及通信機(jī)制1Socket的概念Socket稱為“套接字”,也有人稱為“插座”。在兩臺(tái)計(jì)算機(jī)上運(yùn)行的兩個(gè)程序之間有一個(gè)雙向通信的鏈接點(diǎn),而這個(gè)雙向鏈路的每一端就稱為一個(gè)Socket。建立連接的兩個(gè)程序分別稱為客戶端(Client)和服務(wù)器端(Server)??蛻舳顺绦蛏暾?qǐng)連接,而服務(wù)器端程序監(jiān)聽(tīng)所有的端口,判斷是否有客戶程序的服務(wù)請(qǐng)求。當(dāng)客戶程序請(qǐng)求和某個(gè)端口連接時(shí),服務(wù)器程序就將“

18、套接字”連接到該端口上,此時(shí),服務(wù)器與客戶程序就建立了一個(gè)專用的虛擬連接??蛻舫绦蚩梢韵蛱捉幼謱懭胝?qǐng)求,服務(wù)器程序處理請(qǐng)求并把處理結(jié)果通過(guò)套接字送回。通信結(jié)束時(shí),再將所建的虛擬連接拆除。一個(gè)客戶程序只能連接服務(wù)器的一個(gè)端口,而一個(gè)服務(wù)器可以有若干個(gè)端口,不同的端口使用不同的端口號(hào),并提供不同的服務(wù)。2Socket通信機(jī)制利用Socket進(jìn)行網(wǎng)絡(luò)通信分為三個(gè)步驟:(1) 建立Socket連接。在通信開(kāi)始之前由通信雙方確認(rèn)身份,建立一條專用的虛擬連接通道。(2) 數(shù)據(jù)通信。利用虛擬連接通道傳送數(shù)據(jù)信息進(jìn)行通信。(3) 關(guān)閉。通信結(jié)束時(shí)將所建的虛擬連接拆除。利用包中提供的Socket類和Server

19、Socket類及其方法,可完成上述操作。Socket通信機(jī)制如圖15.3所示。圖15.3 Socket通信機(jī)制 從圖15.3中可以看到,服務(wù)器端的程序首先選擇一個(gè)端口(port)注冊(cè),然后調(diào)用accept()方法對(duì)此端口進(jìn)行監(jiān)聽(tīng),等待其他程序的連接申請(qǐng)。如果客戶端的程序申請(qǐng)和此端口連接,那么服務(wù)器端就利用accept()方法來(lái)取得這個(gè)連接的Socket。客戶端的程序建立Socket時(shí)必須指定服務(wù)器的地址(host)和通信的端口號(hào)(port#),這個(gè)端口號(hào)必須與服務(wù)器端監(jiān)聽(tīng)的端口號(hào)保持一致。15.2.2 Socket類與 ServerSocket類中提供了兩個(gè)類,即ServerSocket類和S

20、ocket類,它們分別用于服務(wù)器端和客戶端的Socket通信,進(jìn)行網(wǎng)絡(luò)通信的方法也都封裝在這兩個(gè)類中。1ServerSocket對(duì)象與Socket對(duì)象的構(gòu)造方法Java在軟件包中提供了ServerSocket類和Socket類對(duì)應(yīng)的雙向鏈接的服務(wù)器端和客戶端,包含的主要構(gòu)造方法如表15.3所示。表15.3 ServerSocket類與Socket類的構(gòu)造方法 2異常處理在建立Socket對(duì)象的同時(shí)要進(jìn)行異常處理,以便程序出錯(cuò)時(shí)能夠及時(shí)做出響應(yīng)。(1) 服務(wù)器端:在建立ServerSocket類的對(duì)象和取得Socket類的對(duì)象時(shí)都要進(jìn)行異常處理,例如下面語(yǔ)句中的try-catch語(yǔ)句。Serve

21、rSocket server;Socket socket;try server=new ServerSocket(3561);catch(Exception e) System.out.println(“Error occurred:”+e);try socket=server.accept();catch(Exception e) System.out.println(Error occurred:+e);(2) 客戶端:在建立Socket類的對(duì)象時(shí)要進(jìn)行異常處理,例如下面的try-catch語(yǔ)句。Socket socket;try socket=new Socket(“Server Nam

22、e”,3561);catch(Exception e) System.out.println(Error occurred:+e);3獲取輸入/輸出流建立Socket連接后,就可以利用Socket類的兩個(gè)方法getInputStream()和getOutputStream()分別獲得向Socket類的對(duì)象讀/寫數(shù)據(jù)的輸入/輸出流。此時(shí)同樣要進(jìn)行異常處理,因此,通常將讀/寫數(shù)據(jù)的輸入/輸出流語(yǔ)句寫在try-catch塊中。例如:try InputStream ins=socket. getInputStream(); OutputStream outs=socket. getOutputStre

23、am();catch(Exception e) System.out.println(“Error occurred:”+e);4讀/寫數(shù)據(jù)流獲取Socket類的對(duì)象的輸入/輸出流后,為了便于進(jìn)行讀/寫,需要在這兩個(gè)流對(duì)象的基礎(chǔ)上建立易于操作的數(shù)據(jù)流對(duì)象,如InputStreamReader類、OutputStreamReader類或PrintStream類的對(duì)象。建立數(shù)據(jù)流的對(duì)象可采用如下語(yǔ)句:InputStreamReader in=new InputStreamReader(ins);BufferedReader inn=new BufferedReader(in);OutputStre

24、amReader out=new InputStreamReader(outs);PrintStream out=new PrintStream(outs);要讀入一個(gè)字符串并將其長(zhǎng)度寫入輸出流中,可以使用如下語(yǔ)句:String str=inn.readLine();Out.println(str.length();5斷開(kāi)連接無(wú)論是編寫服務(wù)器程序還是客戶端程序,通信結(jié)束時(shí),必須斷開(kāi)連接并釋放所占用的資源。Java提供了close()方法來(lái)斷開(kāi)連接。(1) 關(guān)閉Socket對(duì)象:socket.close()。(2) 關(guān)閉Server Socket對(duì)象:server.close()。15.2.3

25、流式Socket通信的示例程序綜合前面介紹的內(nèi)容,這里給出幾個(gè)示例程序作為總結(jié)?!臼纠绦駽15_4.java】 利用InetAddress類的對(duì)象來(lái)獲取計(jì)算機(jī)主機(jī)信息。package ch15;import .InetAddress;import .UnknownHostException;public class C15_4 public static void main(String args ) try if(args.length=1) /調(diào)用InetAddress類的靜態(tài)方法,利用主機(jī)名創(chuàng)建對(duì)象 InetAddress ipa=InetAddress.getByName(args0

26、); System.out.println(Host name: +ipa.getHostName( ); /獲取主機(jī)名 System.out.println(Host IP Address: +ipa.toString( ); /獲取IP地址 System.out.println(Local Host: +InetAddress.getLocalHost( ); else System.out.println(輸入一個(gè)主機(jī)名); catch(UnknownHostException e) /創(chuàng)建InetAddress對(duì)象可能發(fā)生的異常 System.out.println(e.toStrin

27、g( ); /end of main( )運(yùn)行時(shí)先在“ch15項(xiàng)目屬性”對(duì)話框的“主類”后的文本框中輸入“ch15.C15_4”,在“參數(shù)”后的文本框中輸入“l(fā)ocalhost”。然后,選擇菜單欄中的“運(yùn)行”“設(shè)置主項(xiàng)目” “ch15”,再單擊菜單欄中的“運(yùn)行”“清理并生成主項(xiàng)目”。最后,單擊菜單欄中的“運(yùn)行”“運(yùn)行主項(xiàng)目”。程序運(yùn)行后就會(huì)輸出如下的運(yùn)行結(jié)果:Host name: localhostHost IP Address: localhost/Local Host: EKKIVWZMWR79BJH/00下面的示例程序C15_5.java和C15_6.java是一個(gè)完整的實(shí)現(xiàn)Socket

28、通信的Java程序,分別為服務(wù)器端程序和客戶端程序。在這個(gè)Socket通信程序中,服務(wù)器等待與客戶端連接。當(dāng)連接建立后,客戶端向服務(wù)器端發(fā)送一條信息,服務(wù)器端收到后再向客戶端發(fā)送一條信息。若客戶端發(fā)送end結(jié)束消息傳遞,服務(wù)器端同意,則客戶端拆除與服務(wù)器端的連接?!臼纠绦駽15_5.java】 Socket通信的服務(wù)器端程序。package ch15;/Socke服務(wù)器端程序import java.io.*;import .ServerSocket;import .Socket;public class C15_5 public static final int port=8000; pub

29、lic static void main(String args ) String str; try /在端口port注冊(cè)服務(wù) ServerSocket server=new ServerSocket(port); /創(chuàng)建當(dāng)前線程的監(jiān)聽(tīng)對(duì)象 System.out.println(Started: +server); Socket socket=server.accept( ); /負(fù)責(zé)C/S通信的Socket對(duì)象 System.out.println(Socket: +socket); /獲得對(duì)應(yīng)Socket的輸入/輸出流 InputStream fIn=socket.getInputStre

30、am( ); OutputStream fOut=socket.getOutputStream( ); /建立數(shù)據(jù)流 InputStreamReader isr=new InputStreamReader(fIn); BufferedReader in=new BufferedReader(isr); PrintStream out=new PrintStream(fOut); InputStreamReader userisr=new InputStreamReader(System.in); BufferedReader userin=new BufferedReader(userisr)

31、; while(true) System.out.println(等待客戶端的消息); str=in.readLine( ); /讀客戶端傳送的字符串 System.out.println(客戶端:+str); /顯示字符串 if(str.equals(end)break; /如果是end,則退出 System.out.print(給客戶端發(fā)送:); str=userin.readLine( ); out.println(str); /向客戶端發(fā)送消息 if(str.equals(end)break; /while socket.close( ); server.close( ); /try

32、catch(Exception e) System.out.println(異常:+e); 【示例程序C15_6.java】 Socket通信的客戶端程序。package ch15;/Socket客戶端程序import java.io.*;import .InetAddress;import .Socket;public class C15_6 public static void main(String args) String str; try InetAddress addr=InetAddress.getByName(); /InetAddress addr=InetAddress.g

33、etByName(8); Socket socket=new Socket(addr,8000); System.out.println(Socket: +socket); /獲得對(duì)應(yīng)socket的輸入/輸出流 InputStream fIn=socket.getInputStream( ); OutputStream fOut=socket.getOutputStream( ); /建立數(shù)據(jù)流 InputStreamReader isr=new InputStreamReader(fIn); BufferedReader in=new BufferedReader(isr); PrintSt

34、ream out=new PrintStream(fOut); InputStreamReader userisr=new InputStreamReader(System.in); BufferedReader userin=new BufferedReader(userisr); while(true) System.out.print(發(fā)送字符串:); str=userin.readLine( ); /讀取用戶輸入的字符串 out.println(str); /將字符串傳給服務(wù)器端 if(str.equals(end)break; /如果是end,就退出 System.out.print

35、ln(等待服務(wù)器端消息); str=in.readLine( ); /獲取服務(wù)器發(fā)送的字符串 System.out.println(服務(wù)器端字符:+str); if(str.equals(end)break; socket.close( ); /關(guān)閉連接 catch(Exception e) System.out.println(“異常:”+e); 服務(wù)器端程序的運(yùn)行情況如圖15.4所示,客戶端程序的運(yùn)行情況如圖15.5所示。圖15.4 服務(wù)器端程序輸出窗口(ch15(run) 圖15.5 客戶端程序輸出窗口(ch15(#2)程序運(yùn)行時(shí),首先運(yùn)行服務(wù)器程序C15_5.java,然后運(yùn)行客戶端程

36、序C15_6.java建立兩端的連接。輸出窗口有兩個(gè),如圖15.4和圖15.5所示。先在客戶端輸出窗口給服務(wù)器發(fā)送信息,例如“How do you do!”,單擊服務(wù)器窗口,當(dāng)看到服務(wù)器收到信息并輸出后,再給客戶端發(fā)信息,例如“Find,thanks.”,客戶端收到信息并輸出后,再給服務(wù)器發(fā)送信息,直到客戶端給服務(wù)器發(fā)“end”則結(jié)束通信。15.2.4 URL通信與Socket通信的區(qū)別URL通信與Socket通信都是面向連接的通信,它們的區(qū)別在于:Socket通信方式為主動(dòng)等待客戶端的服務(wù)請(qǐng)求方式,而URL通信方式為被動(dòng)等待客戶端的服務(wù)請(qǐng)求方式。利用Socket進(jìn)行通信時(shí),在服務(wù)器端運(yùn)行了一

37、個(gè)Socket通信程序,不停地監(jiān)聽(tīng)客戶端的連接請(qǐng)求,當(dāng)接到客戶端請(qǐng)求后,馬上建立連接并進(jìn)行通信。利用URL進(jìn)行通信時(shí),在服務(wù)器端常駐有一個(gè)CGI程序,但它一直處于睡眠狀態(tài),只有當(dāng)客戶端的連接請(qǐng)求到達(dá)時(shí)它才被喚醒,然后建立連接并進(jìn)行通信。在Socket通信方式中,服務(wù)器端的程序可以打開(kāi)多個(gè)線程與多個(gè)客戶端進(jìn)行通信,并且還可以通過(guò)服務(wù)器使各個(gè)客戶端之間進(jìn)行通信,這種方式適合于一些較復(fù)雜的通信。而在URL通信方式中,服務(wù)器端的程序只能與一個(gè)客戶進(jìn)行通信,這種方式比較適合于B/S通信模式。15.3 UDP通信URL和Socket通信是一種面向連接的流式套接字通信,采用的協(xié)議是TCP協(xié)議。在面向連接的通

38、信中,通信的雙方需要首先建立連接再進(jìn)行通信,這需要占用資源與時(shí)間。但是在建立連接之后,雙方就可以準(zhǔn)確、同步、可靠地進(jìn)行通信了。流式套接字通信在建立連接之后,可以通過(guò)流來(lái)進(jìn)行大量的數(shù)據(jù)交換。TCP通信被廣泛應(yīng)用在文件傳輸、遠(yuǎn)程連接等需要可靠傳輸數(shù)據(jù)的領(lǐng)域。UDP通信是一種無(wú)連接的數(shù)據(jù)報(bào)通信,采用的協(xié)議是數(shù)據(jù)報(bào)通信協(xié)議UDP(User Datagram Protocol)。按照這個(gè)協(xié)議,兩個(gè)程序進(jìn)行通信時(shí)不用建立連接;數(shù)據(jù)以獨(dú)立的包為單位發(fā)送,包的容量不能太大;每個(gè)數(shù)據(jù)報(bào)需要有完整的收/發(fā)地址,可以隨時(shí)進(jìn)行收/發(fā)數(shù)據(jù)報(bào),但不保證傳送順序和內(nèi)容準(zhǔn)確;數(shù)據(jù)報(bào)可能會(huì)被丟失、延誤等。因此,UDP通信是不可

39、靠的通信。由于UDP通信速度較快,因此常常被應(yīng)用在某些要求實(shí)時(shí)交互,準(zhǔn)確性要求不高,但傳輸速度要求較高的場(chǎng)合。軟件包中的類DatagramSocket和類DatagramPacket為實(shí)現(xiàn)UDP通信提供了支持。15.3.1 UDP通信機(jī)制利用UDP通信時(shí),服務(wù)器端和客戶端的通信過(guò)程如圖15.6所示。服務(wù)器端的程序有一個(gè)線程不停地監(jiān)聽(tīng)客戶端發(fā)來(lái)的數(shù)據(jù)報(bào),等待客戶的請(qǐng)求。服務(wù)器只有通過(guò)客戶發(fā)來(lái)的數(shù)據(jù)報(bào)中的信息才能得到客戶端的地址及端口。圖15.6 UDP通信機(jī)制 15.3.2 DatagramSocket類DatagramSocket類用于收/發(fā)數(shù)據(jù)報(bào)。其構(gòu)造方法如下:(1) DatagramSo

40、cket()方法。(2) DatagramSocket(int port)方法。(3) DatagramSocket(int port,InetAddress iaddr)方法。其中,第一個(gè)構(gòu)造方法將Socket連接到本機(jī)的任何一個(gè)可用的端口上;第二個(gè)將Socket連接到本機(jī)的port端口上;第三個(gè)則將Socket連接到指定地址的port端口上。這里需要注意兩點(diǎn):一是規(guī)定端口時(shí)不要發(fā)生沖突;二是在調(diào)用構(gòu)造方法時(shí)要進(jìn)行異常處理。receive()和send()是DatagramSocket類中用來(lái)實(shí)現(xiàn)數(shù)據(jù)報(bào)傳送和接收的兩個(gè)重要成員方法,其格式如下:(1) void receive(Datagra

41、mPacket packet)方法。(2) void send(DatagramPacket packet)方法。receive()方法將使程序中的線程一直處于阻塞狀態(tài),直到從當(dāng)前Socket中接收到信息后,將收到的信息存儲(chǔ)在receive()方法的參數(shù)packet的對(duì)象中。由于數(shù)據(jù)報(bào)是不可靠的通信,因此receive()方法不一定能讀到數(shù)據(jù)。為防止線程死掉,應(yīng)該設(shè)置超時(shí)參數(shù)(timeout)。send()方法將DatagramPacket類的packet的對(duì)象中包含的數(shù)據(jù)報(bào)文發(fā)送到所指定的IP地址主機(jī)的指定端口。15.3.3 DatagramPacket類DatagramPacket類用來(lái)實(shí)

42、現(xiàn)數(shù)據(jù)報(bào)通信,它的常用的兩個(gè)構(gòu)造方法,分別對(duì)應(yīng)發(fā)送數(shù)據(jù)報(bào)和接收數(shù)據(jù)報(bào):(1) DatagramPacket(byte sBuf,int sLength,InetAddress iaddr,int iport)方法。這個(gè)構(gòu)造方法用來(lái)創(chuàng)建發(fā)送數(shù)據(jù)報(bào)對(duì)象。其中,sBuf代表發(fā)送數(shù)據(jù)報(bào)的字節(jié)數(shù)組;sLength代表發(fā)送數(shù)據(jù)報(bào)的長(zhǎng)度;iaddr代表發(fā)送數(shù)據(jù)報(bào)的目的地址,即接收者的IP地址;iport代表發(fā)送數(shù)據(jù)報(bào)的端口號(hào)。(2) DatagramPacket(byte rBuf,int rLength)方法。這個(gè)構(gòu)造方法用來(lái)創(chuàng)建接收數(shù)據(jù)報(bào)對(duì)象。其中,rBuf代表接收數(shù)據(jù)報(bào)的字節(jié)數(shù)組;rLength代表接

43、收數(shù)據(jù)報(bào)的長(zhǎng)度,即讀取的字節(jié)數(shù)。15.3.4 UDP通信示例程序下面通過(guò)建立一個(gè)簡(jiǎn)單的UDP服務(wù)器端和一個(gè)客戶端的程序例子,講述UDP的工作方式。在這個(gè)例子中,服務(wù)器端的程序只是不停地監(jiān)聽(tīng)本機(jī)端口,一旦收到客戶端發(fā)來(lái)的數(shù)據(jù)報(bào),就回應(yīng)一個(gè)簡(jiǎn)單的信息通知客戶已經(jīng)收到了數(shù)據(jù)報(bào)??蛻舳说某绦蛳蚍?wù)器發(fā)送一個(gè)包含一個(gè)字符串的數(shù)據(jù)報(bào),同時(shí)告知服務(wù)器自己的地址及端口,以便服務(wù)器做出回應(yīng)。【示例程序C15_7.java】 UDP通信的服務(wù)器端程序。package ch15;/UDP 服務(wù)器端程序import .DatagramPacket;import .DatagramSocket;import .Inet

44、Address;class UDPServerThread extends Thread /啟動(dòng)服務(wù)器線程的主程序 private DatagramPacket packet; private DatagramSocket socket; static final int sport=1777; UDPServerThread() try /將Socket連接到本機(jī)的一個(gè)可用端口上 socket=new DatagramSocket(sport); System.out.println(Listening on port:+socket.getLocalPort(); catch(Except

45、ion e) System.out.println(Error:+e); public void run() /線程的主要操作 if(socket=null)return; while(true) try InetAddress address; int cport; byte buf1=new byte1000,buf2=new byte1000; String s=Your packet is received; packet=new DatagramPacket(buf1,buf1.length); /生成一個(gè)接收數(shù)據(jù)報(bào) socket.receive(packet); /接收數(shù)據(jù)報(bào) String s1=new String(packet.getData(); System.out.println(Received from client: +s1); /打印數(shù)據(jù)報(bào)的內(nèi)容 address=packet.getAddress(); cport=packet.getPort(); /獲得數(shù)據(jù)報(bào)的源地址與端口 buf2=s.getBytes(); packet=new DatagramPacket(buf2,buf2.

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論