第14章Java網(wǎng)絡(luò)編程_第1頁(yè)
第14章Java網(wǎng)絡(luò)編程_第2頁(yè)
第14章Java網(wǎng)絡(luò)編程_第3頁(yè)
第14章Java網(wǎng)絡(luò)編程_第4頁(yè)
第14章Java網(wǎng)絡(luò)編程_第5頁(yè)
已閱讀5頁(yè),還剩39頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、.URL類(lèi)是包中的一個(gè)重要的類(lèi),URL的實(shí)例封裝著一個(gè)統(tǒng)一資源定位符(Uniform Resource Locator),使用URL創(chuàng)建對(duì)象的應(yīng)用程序稱(chēng)作客戶(hù)端程序。一個(gè)URL對(duì)象封裝著著一個(gè)具體的資源的引用,表明客戶(hù)要訪問(wèn)這個(gè)URL中的資源,客戶(hù)利用URL對(duì)象可以獲取URL中的資源。一個(gè)URL對(duì)象通常包含最基本的三部分信息:協(xié)議、地址、資源。協(xié)議必須是URL對(duì)象所在的Java虛擬機(jī)支持的協(xié)議,許多協(xié)議并不為我們所常用,而常用的Http、Ftp、File協(xié)議都是虛擬機(jī)支持的協(xié)議;地址必須是能連接的有效IP地址或域名;資源可以是主機(jī)上的任何一個(gè)文件 .URL類(lèi)通常使用如下的構(gòu)造方法創(chuàng)建一個(gè)URL

2、對(duì)象:public URL(String spec) throws MalformedURLException該構(gòu)造方法使用字符串初始化一個(gè)URL對(duì)象 .另一個(gè)常用的構(gòu)造方法是:public URL(String protocol, String host,String file) throws MalformedURLException該構(gòu)造方法構(gòu)造使用的協(xié)議、地址和資源分別由參數(shù)protocol、host和file指定 .URL對(duì)象調(diào)用InputStream openStream() 方法可以返回一個(gè)輸入流,該輸入流指向URL對(duì)象所包含的資源。通過(guò)該輸入流可以將服務(wù)器上的資源信息讀入到客戶(hù)

3、端。URL對(duì)象調(diào)用InputStream openStream() 方法可以返回一個(gè)輸入流,該輸入流指向URL對(duì)象所包含的資源。通過(guò)該輸入流可以將服務(wù)器上的資源讀入到客戶(hù)端 .14.2.1 地址的表示 Internet上的主機(jī)有兩種方式表示地址:1域名例如,2IP 地址例如,包中的InetAddress類(lèi)對(duì)象含有一個(gè)Internet主機(jī)地址的域名和IP地址: .1獲取Internet上主機(jī)的地址可以使用InetAddress類(lèi)的靜態(tài)方法:getByName(String s);將一個(gè)域名或IP地址傳遞給該方法的參數(shù)s,獲得一個(gè)InetAddress對(duì)象,該對(duì)象含有主機(jī)地址的域名和IP地址,該對(duì)

4、象用如下格式表示它包含的信息: .另外,InetAddress類(lèi)中還有兩個(gè)實(shí)例方法:public String getHostName() 獲取InetAddress對(duì)象所含的域名。public String getHostAddress() 獲取InetAddress對(duì)象所含的IP地址。.2獲取本地機(jī)的地址我們可以使用InetAddress類(lèi)的靜態(tài)方法:getLocalHost()獲得一個(gè)InetAddress對(duì)象,該對(duì)象含有本地機(jī)的域名和IP地址。 .14.3.1 套接字 網(wǎng)絡(luò)通信使用IP地址標(biāo)識(shí)Internet上的計(jì)算機(jī),使用端口號(hào)標(biāo)識(shí)服務(wù)器上的進(jìn)程(程序)。也就是說(shuō),如果服務(wù)器上的一個(gè)

5、程序不占用一個(gè)端口號(hào),用戶(hù)程序就無(wú)法找到它,就無(wú)法和該程序交互信息。端口號(hào)被規(guī)定為一個(gè)16位的065535之間的整數(shù),其中,01023被預(yù)先定義的服務(wù)通信占用(如telnet占用端口23,http占用端口80等),除非我們需要訪問(wèn)這些特定服務(wù),否則,就應(yīng)該使用102465535這些端口中的某一個(gè)進(jìn)行通信,以免發(fā)生端口沖突 當(dāng)兩個(gè)程序需要通信時(shí),它們可以通過(guò)使用Socket類(lèi)建立套接字對(duì)象并連接在一起 .客戶(hù)端的程序使用Socket類(lèi)建立負(fù)責(zé)連接到服務(wù)器的套接字對(duì)象。Socket的構(gòu)造方法是:Socket(String host,int port),參數(shù)host是服務(wù)器的IP地址,port是一個(gè)

6、端口號(hào)。建立套接字對(duì)象可能發(fā)生IOException異常,因此應(yīng)象下面那樣建立連接到服務(wù)器的套接字對(duì)象:try Socket mysocket=new Socket(,2010);catch(IOException e).為了能使客戶(hù)成功地連接到服務(wù)器,服務(wù)器必須建立一個(gè)ServerSocket對(duì)象,該對(duì)象通過(guò)將客戶(hù)端的套接字對(duì)象和服務(wù)器端的一個(gè)套接字對(duì)象連接起來(lái),從而達(dá)到連接的目的。ServerSocket的構(gòu)造方法是:ServerSocket(int port),port是一個(gè)端口號(hào)。port必須和客戶(hù)呼叫的端口號(hào)相同。當(dāng)建立ServerSocket對(duì)象時(shí)可能發(fā)生IOException異常

7、,因此應(yīng)象下面那樣建立ServerSocket對(duì)象:try ServerSocket serverForClient = new ServerSocket(2010);catch(IOException e).當(dāng)服務(wù)器的ServerSocket對(duì)象serverForClient建立后,就可以使用方法accept()將客戶(hù)的套接字和服務(wù)器端的套接字連接起來(lái),代碼如下所示:try Socket sc = serverForClient.accept();catch(IOException e).客戶(hù)端的Socket輸入流輸出流服務(wù)器端Socket輸出流輸入流圖14.2 套接字連接示意圖互相連接互相

8、連接.連接建立后,服務(wù)器端的套接字對(duì)象調(diào)用getInetAddress()方法可以獲取一個(gè)InetAddess對(duì)象,該對(duì)象含有客戶(hù)端的IP地址和域名,同樣,客戶(hù)端的套接字對(duì)象調(diào)用getInetAddress()方法可以獲取一個(gè)InetAddess對(duì)象,該對(duì)象含有服務(wù)器端的IP地址和域名。 雙方通信完畢后,套接字應(yīng)使用close()方法關(guān)閉套接字連接 .從套接字連接中讀取數(shù)據(jù)與從文件中讀取數(shù)據(jù)有著很大的不同。盡管二者都是輸入流,但從文件中讀取數(shù)據(jù)時(shí),所有的數(shù)據(jù)都已經(jīng)在文件中了,而使用套接字連接時(shí),可能在另一端數(shù)據(jù)發(fā)送出來(lái)之前,就已經(jīng)開(kāi)始試著讀取了,這時(shí),就會(huì)堵塞本線程,直到該讀取方法成功讀取到信

9、息,本線程才繼續(xù)執(zhí)行后續(xù)的操作。因此,服務(wù)器端收到一個(gè)客戶(hù)的套接字后,就應(yīng)該啟動(dòng)一個(gè)專(zhuān)門(mén)為該客戶(hù)服務(wù)的線程 .服務(wù)器程序客戶(hù)1的線程客戶(hù)1客戶(hù)2的線程客戶(hù)2客戶(hù)3的線程客戶(hù)3圖14.5 具有多線程的服務(wù)器端程序.可以使用Socket類(lèi)的不帶參數(shù)的構(gòu)造方法Socket()創(chuàng)建一個(gè)套接字對(duì)象,該對(duì)象再調(diào)用 public void connect(SocketAddress endpoint) throws IOException請(qǐng)求和參數(shù)SocketAddress指定地址的服務(wù)器端的套接字建立連接。為了使用connect方法,可以使用SocketAddress的子類(lèi):InetSocketAddre

10、ss創(chuàng)建一個(gè)對(duì)象,InetSocketAddress的構(gòu)造方法是: public InetSocketAddress(InetAddress addr, int port).基于UDP的通信和基于TCP的通信不同,基于UDP的信息傳遞更快,但不提供可靠性保證。也就是說(shuō),數(shù)據(jù)在傳輸時(shí),用戶(hù)無(wú)法知道數(shù)據(jù)能否正確到達(dá)目的地主機(jī),也不能確定數(shù)據(jù)到達(dá)目的地的順序是否和發(fā)送的順序相同??梢园裊DP通信比作生活中的郵遞信件,我們不能肯定所發(fā)的信件就一定能夠到達(dá)目的地,也不能肯定到達(dá)的順序是發(fā)出時(shí)的順序,可能因?yàn)槟撤N原因?qū)е潞蟀l(fā)出的先到達(dá)。 .基于UDP通信的基本模式是:將數(shù)據(jù)打包,稱(chēng)為數(shù)據(jù)包(好比將信件裝入

11、信封一樣),然后將數(shù)據(jù)包發(fā)往目的地。接受別人發(fā)來(lái)的數(shù)據(jù)包(好比接收信封一樣),然后查看數(shù)據(jù)包中的內(nèi)容。.1用DatagramPacket類(lèi)將數(shù)據(jù)打包,即用DatagramPacket類(lèi)創(chuàng)建一個(gè)對(duì)象,稱(chēng)為數(shù)據(jù)包。用DatagramPacket的以下兩個(gè)構(gòu)造方法創(chuàng)建待發(fā)送的數(shù)據(jù)包: DatagramPacket(byte data,int length,InetAddtress address,int port):.使用該構(gòu)造方法創(chuàng)建的數(shù)據(jù)包對(duì)象具有下列兩個(gè)性質(zhì):含有data數(shù)組指定的數(shù)據(jù)。該數(shù)據(jù)包將發(fā)送到地址是address、端口號(hào)是port的主機(jī)上。我們稱(chēng)address是它的目標(biāo)地址、port

12、是這個(gè)數(shù)據(jù)包的目標(biāo)端口。DatagramPack(byte data,int offset,int length,InetAddtress address,int port)使用該構(gòu)造方法創(chuàng)建的數(shù)據(jù)包對(duì)象含有數(shù)組data中從offset開(kāi)始后的length個(gè)字節(jié),該數(shù)據(jù)包將發(fā)送到地址是address,端口號(hào)是port的主機(jī)上。 .2用DatagramSocket類(lèi)的不帶參數(shù)的構(gòu)造方法:DatagramSocket()創(chuàng)建一個(gè)對(duì)象,該對(duì)象負(fù)責(zé)發(fā)送數(shù)據(jù)包。例如:DatagramSocket mail_out=new DatagramSocket();mail_out.send(data_pack)

13、;.首先用DatagramSocket的另一個(gè)構(gòu)造方法:DatagramSocket(int port) 創(chuàng)建一個(gè)對(duì)象,其中的參數(shù)必須和待接收的數(shù)據(jù)包的端口號(hào)相同。例如,如果發(fā)送方發(fā)送的數(shù)據(jù)包的端口是5666,那么如下創(chuàng)建DatagramSocket對(duì)象:DatagramSocket mail_in=new DatagramSocket(5666); .然后對(duì)象mail_in使用方法receive(DatagramPacket pack)接受數(shù)據(jù)包。該方法有一個(gè)數(shù)據(jù)包參數(shù)pack,方法receive把收到的數(shù)據(jù)包傳遞給該參數(shù)。因此我們必須預(yù)備一個(gè)數(shù)據(jù)包以便收取數(shù)據(jù)包。這時(shí)需使用 Datagra

14、mPack類(lèi)的另外一個(gè)構(gòu)造方法:DatagramPack(byte data,int length)創(chuàng)建一個(gè)數(shù)據(jù)包,用于接收數(shù)據(jù)包,例如:byte data=new byte100;int length=90;DatagramPacket pack=new DatagramPacket(data,length);mail_in.receive(pack);該數(shù)據(jù)包pack將接收長(zhǎng)度是length字節(jié)的數(shù)據(jù)放入data。 .計(jì)算機(jī)使用IP地址和端口來(lái)區(qū)分其位置和進(jìn)程,但有一類(lèi)地址非常特殊,稱(chēng)作D類(lèi)地址,D類(lèi)地址不是用來(lái)代表位置的,即在網(wǎng)絡(luò)上不能使用D類(lèi)地址去查找計(jì)算機(jī)。 D類(lèi)地址好像生活中的社團(tuán)

15、組織,不同地理位置的人可以加入相同的組織,繼而可以享有組織內(nèi)部的通信權(quán)利。 .Internet的地址是a.b.c.d的形式。該地址的一部分代表用戶(hù)自己的主機(jī),而另一部分代表用戶(hù)所在的網(wǎng)絡(luò)。當(dāng)a小于128,那么b.c.d就用來(lái)表示主機(jī),這類(lèi)地址稱(chēng)做A類(lèi)地址。如果a大于等于128并且小于192,則a.b表示網(wǎng)絡(luò)地址,而c.d表示主機(jī)地址,這類(lèi)地址稱(chēng)做B類(lèi)地址。如果a大于等于192,則網(wǎng)絡(luò)地址是a.b.c,d表示主機(jī)地址,這類(lèi)地址稱(chēng)做C類(lèi)地址。55是保留地址,稱(chēng)作D類(lèi)地址 .要廣播或接收廣播的主機(jī)都必須加入到同一個(gè)D類(lèi)地址。一個(gè)D類(lèi)地址也稱(chēng)做一個(gè)組播地址,

16、D類(lèi)地址并不代表某個(gè)特定主機(jī)的位置,一個(gè)具有A、B或C類(lèi)地址的主機(jī)要廣播數(shù)據(jù)或接收廣播,都必須加入到同一個(gè)D類(lèi)地址。 .RMI(Remote Method Invocation)是一種分布式技術(shù),使用RMI可以讓一個(gè)虛擬機(jī)上的應(yīng)用程序請(qǐng)求調(diào)用位于網(wǎng)絡(luò)上另一處的虛擬機(jī)上的對(duì)象方法。習(xí)慣上稱(chēng)發(fā)出調(diào)用請(qǐng)求的虛擬機(jī)為(本地)客戶(hù)機(jī),稱(chēng)接受并執(zhí)行請(qǐng)求的虛擬機(jī)為(遠(yuǎn)程)服務(wù)器 .1遠(yuǎn)程對(duì)象駐留在(遠(yuǎn)程)服務(wù)器上的對(duì)象是客戶(hù)要請(qǐng)求的對(duì)象,稱(chēng)作遠(yuǎn)程對(duì)象,即客戶(hù)程序請(qǐng)求遠(yuǎn)程對(duì)象調(diào)用方法,然后遠(yuǎn)程對(duì)象調(diào)用方法并返回必要的結(jié)果。 .2代理與存根(Stub)RMI不希望客戶(hù)應(yīng)用程序直接與遠(yuǎn)程對(duì)象打交道,代替地讓用戶(hù)程

17、序和遠(yuǎn)程對(duì)象的代理打交道。代理的特點(diǎn)是:它與遠(yuǎn)程對(duì)象實(shí)現(xiàn)了相同的接口,也就是說(shuō)它與遠(yuǎn)程對(duì)象向用戶(hù)公開(kāi)了相同的方法,當(dāng)用戶(hù)請(qǐng)求代理調(diào)用這樣的方法時(shí),如果代理確認(rèn)遠(yuǎn)程對(duì)象能調(diào)用相同的方法時(shí),就把實(shí)際的方法調(diào)用委派給遠(yuǎn)程對(duì)象。 .RMI會(huì)幫助我們生成一個(gè)存根(Stub):一種特殊的字節(jié)碼,并讓這個(gè)存根產(chǎn)生的對(duì)象為作為遠(yuǎn)程對(duì)象的代理。代理需要駐留在客戶(hù)端,也就是說(shuō),需要把RMI生成的存根(Stub)復(fù)制或下載到客戶(hù)端。因此,在RMI中,用戶(hù)實(shí)際上是在和遠(yuǎn)程對(duì)象的代理直接打交道,但用戶(hù)并沒(méi)有感覺(jué)到他在和一個(gè)代理打交道,而是覺(jué)得自己就是在和遠(yuǎn)程對(duì)象直接打交道。比如,用戶(hù)想請(qǐng)求遠(yuǎn)程對(duì)象調(diào)用某個(gè)方法,只需將向

18、遠(yuǎn)程代理發(fā)出同樣的請(qǐng)求即可 .(本地)客戶(hù)機(jī)遠(yuǎn)程代理客戶(hù)應(yīng)用程序請(qǐng)求(遠(yuǎn)程)服務(wù)器遠(yuǎn)程對(duì)象請(qǐng)求響應(yīng)圖14.12 遠(yuǎn)程代理與遠(yuǎn)程對(duì)象響應(yīng).3Remote接口RMI為了標(biāo)識(shí)一個(gè)對(duì)象是遠(yuǎn)程對(duì)象,即可以被客戶(hù)請(qǐng)求的對(duì)象,要求遠(yuǎn)程對(duì)象必須實(shí)現(xiàn)java.rmi包中的Remote接口,也就是說(shuō)只有實(shí)現(xiàn)該接口的類(lèi)的實(shí)例才被RMI認(rèn)為是一個(gè)遠(yuǎn)程對(duì)象。Remote接口中沒(méi)有方法,該接口僅僅起到一個(gè)標(biāo)識(shí)作用,因此,必須擴(kuò)展Remote接口,以便規(guī)定遠(yuǎn)程對(duì)象的那些方法是客戶(hù)可以請(qǐng)求的方法,用戶(hù)程序不必編寫(xiě)和遠(yuǎn)程代理的有關(guān)代碼,只需知道遠(yuǎn)程代理和遠(yuǎn)程對(duì)象實(shí)現(xiàn)了相同的接口 .為了敘述的方便,我們假設(shè)本地客戶(hù)機(jī)存放有關(guān)類(lèi)的

19、目錄是D:Client;遠(yuǎn)程服務(wù)器的IP是,存放有關(guān)類(lèi)的目錄是D:Server。 .1擴(kuò)展Remote接口定義一個(gè)接口是java.rmi包中Remote的子接口,即擴(kuò)展Remote接口。以下是我們定義的Remote的子接口是RemoteSubject。RemoteSubject子接口中定義了計(jì)算面積的方法,即要求遠(yuǎn)程對(duì)象為用戶(hù)計(jì)算某種幾何圖形的面積。RemoteSubject的代碼如下:RemoteSubject.java RemoteSubject.java import java.rmi.*;public interface RemoteSubject extends R

20、emote public void setHeight(double height) throws RemoteException; public void setWidth(double width) throws RemoteException; public double getArea() throws RemoteException;.2遠(yuǎn)程對(duì)象創(chuàng)建遠(yuǎn)程對(duì)象的類(lèi)必須要實(shí)現(xiàn)Remote接口,RMI使用Remote接口來(lái)標(biāo)識(shí)遠(yuǎn)程對(duì)象,但是Remote中沒(méi)有方法,因此創(chuàng)建遠(yuǎn)程對(duì)象的類(lèi)需要實(shí)現(xiàn)Remote接口的一個(gè)子接口。另外,RMI為了讓一個(gè)對(duì)象成為遠(yuǎn)程對(duì)象還需要進(jìn)行一些必要初始化工作,因

21、此,在編寫(xiě)創(chuàng)建遠(yuǎn)程對(duì)象的類(lèi)時(shí),可以簡(jiǎn)單讓該類(lèi)是RMI提供的java.rmi.server包中的UnicastRemoteObject類(lèi)的子類(lèi)即可。 .以下是我們定義的創(chuàng)建遠(yuǎn)程對(duì)象的類(lèi):RemoteConcreteSubject,該類(lèi)實(shí)現(xiàn)了上述RemoteSubject接口(見(jiàn)本節(jié)上述標(biāo)題1中的RemoteSubject接口),所創(chuàng)建的遠(yuǎn)程對(duì)象可以計(jì)算矩形的面積,RemoteConcreteSubject的代碼如下:RemoteConcreteSubject.java RemoteConcreteSubject.java import java.rmi.*;import java.rmi.ser

22、ver.UnicastRemoteObject;public class RemoteConcreteSubject extends UnicastRemoteObject implements RemoteSubject double width,height; public RemoteConcreteSubject() throws RemoteException public void setWidth(double width) throws RemoteException this.width=width; public void setHeight(double height)

23、throws RemoteException this.height=height; public double getArea() throws RemoteException return width*height; .3. 存根(Stub)與代理RMI負(fù)責(zé)產(chǎn)生存根(Stub Object),如果創(chuàng)建遠(yuǎn)程對(duì)象的字節(jié)碼是RemoteConcreteSubject.class,那么存根(Stub)的字節(jié)碼是RemoteConcreteSubject_Stub.class,即后綴為“_Stub”。RMI使用rmic命令生成存根:RemoteConcreteSubject_Stub.class。首

24、先進(jìn)入D:Server目錄,然后如下執(zhí)行rmic命令:rmic RemoteConcreteSubject執(zhí)行過(guò)rmic命令將產(chǎn)生的存根:RemoteConcreteSubject_Stub.class .4.啟動(dòng)注冊(cè):rmiregistry在遠(yuǎn)程服務(wù)器創(chuàng)建遠(yuǎn)程對(duì)象之前,RMI要求遠(yuǎn)程服務(wù)器必須首先啟動(dòng)注冊(cè):rmiregistry,只有啟動(dòng)了rmiregistry,遠(yuǎn)程服務(wù)器才可以創(chuàng)建遠(yuǎn)程對(duì)象,并將該對(duì)象注冊(cè)到rmiregistry所管理的注冊(cè)表中。在遠(yuǎn)程服務(wù)器開(kāi)啟一個(gè)終端,比如在MS-DOS命令行窗口進(jìn)入D:Server目錄,然后執(zhí)行rimregistry命令:圖14.14 啟動(dòng)注冊(cè)rmiregistry啟動(dòng)注冊(cè),也可以后臺(tái)啟動(dòng)注冊(cè):start rmiregistry .5.啟動(dòng)遠(yuǎn)程對(duì)象服務(wù)遠(yuǎn)程服務(wù)器啟動(dòng)注冊(cè)rmiregistry后,遠(yuǎn)程服務(wù)器就可以啟動(dòng)遠(yuǎn)程對(duì)象服務(wù)了,即編寫(xiě)程序來(lái)創(chuàng)建和注冊(cè)遠(yuǎn)程對(duì)象,并運(yùn)行該程序。遠(yuǎn)程服務(wù)器使用java.rmi包中的Naming類(lèi)調(diào)用其類(lèi)方法:rebind(String name, R

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論