《Java語言程序設(shè)計(jì)》課件第10章_第1頁
《Java語言程序設(shè)計(jì)》課件第10章_第2頁
《Java語言程序設(shè)計(jì)》課件第10章_第3頁
《Java語言程序設(shè)計(jì)》課件第10章_第4頁
《Java語言程序設(shè)計(jì)》課件第10章_第5頁
已閱讀5頁,還剩55頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

10.1InetAddress類和URL類10.2流套接字Socket編程

10.3數(shù)據(jù)報(bào)UDP編程10.4小結(jié)

10.5習(xí)題

10.1.1InetAdress類

J包中的InetAddress類封裝了Java對IP地址的處理,是Java對IP地址的一些處理。InetAddress有兩個(gè)子類Inet4Address和Inet6Address,分別實(shí)現(xiàn)IPV4地址和IPV6地址,InetAddress是其二者的父類,既可以實(shí)現(xiàn)IPV4地址,也可以實(shí)現(xiàn)IPV6地址。10.1InetAddress類和URL類

InetAddress對象保存了網(wǎng)絡(luò)中計(jì)算機(jī)的主機(jī)名和IP地址,可以通過調(diào)用以下靜態(tài)方法來獲?。?/p>

●?getLocalhost()方法可以獲取本機(jī)的IP地址,如果網(wǎng)絡(luò)適配器設(shè)置了IP則顯示IP,沒有設(shè)置則返回本機(jī)回環(huán)地址。

●?getByName(Stringhost)方法可以獲取由host參數(shù)指定計(jì)算機(jī)的IP地址。

●getAllByName(Stringhost)方法可以獲取由host參數(shù)指定計(jì)算機(jī)的多個(gè)IP地址,Internet上有些機(jī)器除了回環(huán)地址,還會隨網(wǎng)絡(luò)適配器不同而設(shè)置多個(gè)不同的IP地址,該方法返回的IP地址存儲在對象數(shù)組中。●?getByAddress(byte[]addr)方法通過addr字節(jié)數(shù)組(IPV4為4字節(jié)地址,IPV6為10字節(jié)地址)來創(chuàng)建一個(gè)IP地址對象。

●?getByAddress(Stringhost,byte[]addr)方法由host指定的主機(jī)和addr字節(jié)數(shù)組指定的IP來創(chuàng)建一個(gè)IP地址對象。

若指定的主機(jī)名或IP地址無法解析,則會顯示異常,一般以try{}catch{}結(jié)構(gòu)捕獲異常,即

try

{InetAddressaddress=InetAddress.getByName("");}

catch(UnknownHostExceptionex)

{System.out.println("Couldnotfindcn.suncom");}例10-1用InetAdress類的方法來獲取本機(jī)地址、本機(jī)回路地址,以及遠(yuǎn)程的地址。

【例10-1】InetAdress類的使用。

import.*;

publicclassIPAddress

{

publicstaticvoidmain(String[]args)throwsUnknownHostException{ InetAddressaddr1=InetAddress.getLocalHost();

InetAddressaddr2=InetAddress.getByName("");

InetAddressaddr3=InetAddress.getByName("localhost");

System.out.println(addr1);

System.out.println("主機(jī)名: "+addr1.getHostName()+"IP地址:"+addr1.getHostAddress()+"\n");

System.out.println("SUN公司主機(jī):"); System.out.println(addr2);

System.out.println("主機(jī)名: "+addr2.getHostName()+"IP地址:"+addr2.getHostAddress()+"\n");

System.out.println("本機(jī)回路地址:");

System.out.println(addr3);

System.out.println("主機(jī)名: "+addr3.getHostName()+"IP地址:"+addr3.getHostAddress());

}

}

運(yùn)行結(jié)果如圖10-1所示。圖10-1IP地址10.1.2URL類

URL(UniformResourceLocator)統(tǒng)一資源定位符用來表示Ineternet上某個(gè)資源的地址,其語法格式如下:

protocol://host[:port]/path

protocol://username:password@host[:port]/path

其中,protocol為具體的協(xié)議,如http、ftp、file等;host為主機(jī)名;port為協(xié)議所使用的端口號;path為資源的路徑名。第二種格式常用于ftp文件傳輸?shù)馁Y源獲取。username和password分別為用戶名和用戶口令。

Java使用URL類的各種構(gòu)造方法來構(gòu)造URL對象,具體如下:

●?publicURL(Stringspec):通過字符串spec參數(shù)來指定一個(gè)URL對象,如:

URLurl=newURL(“”);

●?publicURL(URLcontext,Stringspec):通過參數(shù)context基本的URL地址,再來構(gòu)造與之相對位置的URL。如URLcontext=newURL("");URLurl=newURL(context,"index.htm"),就是構(gòu)造了一個(gè)相對與基地址的資源“index.html”?!?publicURL(Stringprotocol,Stringhost,Stringfile):通過protocol來指定協(xié)議,host參數(shù)指定主機(jī),file指定具體的資源文件。

●?publicURL(Stringprotocol,Stringhost,intport,Stringfile):同上構(gòu)造方法,只是端口不同時(shí)通過port參數(shù)來指定。

若構(gòu)造URL的字符不符合URL地址規(guī)范,則會顯示MalformedURLException異常,如:

try

{URLu1=newURL(“”);

}catch(MalformedURLExceptionex){}此外,URL類還提供一些方法來獲取URL對象的不同部分:getProtocol()獲取協(xié)議名稱,getHost()獲取主機(jī)名,getPort()獲取資源的端口號,getFile()獲取具體資源文件名,getPath()獲取資源的URL路徑,getAuthority()獲取URL的權(quán)限信息等。

URL對象通過調(diào)用openStream()來獲取InputStream的數(shù)據(jù)流。如例10-2創(chuàng)建一個(gè)URL對象u,再調(diào)用openStream()方法將獲取資源的字符流讀入流對象in中,并將讀入的流一行行加入文本區(qū)域taf中。例程運(yùn)行結(jié)果如圖10-2所示。【例10-2】讀取遠(yuǎn)程文件。

importjava.awt.*;

importjava.awt.event.*;

importjavax.swing.*;

import.*;

importjava.io.*;

publicclassShowWebFileextendsJFrame

{

privateJlabellfn=newJlabel("文件名:"); privateJtextFieldtfu=newJtextField("http://index.php",20);

privateJbuttonsearb=newJbutton("查找");

privateJtextAreataf=newJtextArea();

privateJlabellstatus=newJlabel();

privateJpanelp=newJpanel();

publicShowWebFile(Strings)

{ super(s);

Containerc=getContentPane();

searb.addActionListener(newActionListener()

{

publicvoidactionPerformed(ActionEvente)

{ Stringline;

Stringfilename=tfu.getText();

taf.setText(null);

try{ URLu=newURL(filename);

InputStreamin=u.openStream();

BufferedReaderinFile=newBufferedReader(newInputStreamReader(in));

while((line=inFile.readLine())!=null)

{

taf.append(line+'\n');

}

lstatus.setText(filename+"文件讀取成功!");}

catch(MalformedURLExceptionex){lstatus.setText(filename+

“文件格式錯(cuò)誤!”);}

catch(FileNotFoundExceptionex){lstatus.setText(filename+

"文件沒有發(fā)現(xiàn)!");}

catch(IOExceptionex){lstatus.setText(ex.toString());}

}

});

c.setLayout(newBorderLayout());

c.add(p,BorderLayout.NORTH); c.add(newJscrollPane(taf),BorderLayout.CENTER);

c.add(lstatus,BorderLayout.SOUTH);

p.setLayout(newBorderLayout());

p.add(lfn,BorderLayout.WEST);

p.add(tfu,BorderLayout.CENTER);

p.add(searb,BorderLayout.EAST);

} publicstaticvoidmain(String[]args)

{

ShowWebFilef=newShowWebFile(“顯示遠(yuǎn)程文件”);

f.setSize(500,300);

f.setVisible(true);

f.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);

}

}圖10-2URL獲取資源網(wǎng)絡(luò)套接字是對網(wǎng)絡(luò)通信的一種抽象,可以將其想象為一種連接設(shè)備,這個(gè)設(shè)備將網(wǎng)絡(luò)上的數(shù)據(jù)流連接傳輸?shù)接脩舫绦蛑?。連接網(wǎng)絡(luò)兩端各有一個(gè)套接字,套接字之間是一條網(wǎng)絡(luò)通信線路,服務(wù)器上的應(yīng)用程序和客戶端上的應(yīng)用程序通過套接字來傳輸數(shù)據(jù)流,可以忽略網(wǎng)絡(luò)上數(shù)據(jù)流傳輸?shù)募?xì)節(jié)。

流套接字使用TCP協(xié)議來進(jìn)行傳輸控制,它是一種面向連接的協(xié)議,能夠檢測數(shù)據(jù)在傳輸過程中丟失的包,以便重新傳輸。10.2流套接字Socket編程

Java套接字Socket編程一般有兩個(gè)類型:套接字(Socket)和服務(wù)器套接字(ServerSocket),用來實(shí)現(xiàn)客戶端/服務(wù)器(C/S)結(jié)構(gòu)的編程。使用Socket編程一般是在服務(wù)器端監(jiān)聽(Listen)某個(gè)端口是否有客戶端的請求,當(dāng)客戶端發(fā)出連接請求后,服務(wù)器端接受(Accept)請求,并發(fā)送accept的消息,這樣連接建立起來以后,通過send()等方法就可以發(fā)送和接收數(shù)據(jù)。一般Socket過程為:創(chuàng)建Socket,打開輸入/輸出流,進(jìn)行讀/寫操作,關(guān)閉Socket。

Socket和ServerSocket構(gòu)造方法可通過不同的參數(shù),諸如IP地址、端口號等來創(chuàng)建。Socket和ServerSocket通過getInputStream()和getOutputStream()來獲取對應(yīng)的輸入/輸出流,實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)的讀/寫操作,ServerSocket調(diào)用accetp()方法來接收連接,調(diào)用close()方法來關(guān)閉Socket。

例10-3構(gòu)建了一個(gè)ServerSocket的服務(wù)器端程序。例10-4構(gòu)建了一個(gè)客戶端Socket,ServerSocket和Socket之間互相通信來傳輸信息?!纠?0-3】服務(wù)器端程序MyServer.java。

import.*;

importjava.io.*;

publicclassMyServer

{

publicstaticvoidmain(String[]args)throwsIOException

{

ServerSocketserver=newServerSocket(8080);

try

{System.out.println

("服務(wù)器程序啟動(dòng),開始監(jiān)聽客戶的請求...");

Socketskt=server.accept();

try

{

?System.out.println("接受客戶:"+skt.getInetAddress()+"的連接請求,開始通信...");

?DataInputStreamin=newDataInputStream(newBufferedInputStream(skt.getInputStream()));

DataOutputStreamout=newDataOutputStream(newBufferedOutputStream

(skt.getOutputStream()));while(true)

{

doublelength=in.readDouble();

System.out.println("從客戶接收到圓的直徑:"+length);

doublearea=Math.PI*length*length;

out.writeDouble(area);

out.flush();

System.out.println("圓的面積為:"+area);

inti=in.readInt();

if(i==0)break;}

}catch(IOExceptione){System.err.println(e);}

finally{skt.close();System.out.println("通信結(jié)束!");}

}catch(IOExceptione){System.err.println(e);}

finally{server.close();}

}

}【例10-4】客戶端程序MyClient.java。

import.*;

importjava.io.*;

publicclassMyClient

{

publicstaticvoidmain(String[]args)throwsException

{

InetAddressaddr=InetAddress.getByName("localhost");

Socketskt=newSocket(addr,8080);

try

{DataInputStreamin=newDataInputStream(newBufferedInputStream

(skt.getInputStream()));

DataOutputStreamout=newDataOutputStream(newBufferedOutputStream

(skt.getOutputStream()));

BufferedReaderstdin=newBufferedReader(newInputStreamReader(System.in),1);

stop:while(true)

{System.out.print("請輸入圓的直徑:");

Strings1=stdin.readLine();

doublelength=Double.parseDouble(s1);

out.writeDouble(length);

out.flush();

doublearea=in.readDouble();

System.out.println("從服務(wù)器接收到圓的面積為:"+area);

while(true)

{System.out.print("繼續(xù)計(jì)算?(Y/N)");

Strings2=stdin.readLine();

if(s2.equals("N")||s2.equals("n"))

{

out.writeInt(0);

out.flush();

breakstop;

}

elseif(s2.equals("Y")||s2.equals("y"))

{out.writeInt(1);

out.flush();

break;

}

}

?}

}

catch(IOExceptione){System.err.println(e);}

finally{skt.close();}

}

}在MyServer.java程序中創(chuàng)建ServerSocket,ServerSocket接受的連接對象為skt,Server端等待客戶端連接,連接建立后輸出“接受客戶xxx.xxx.xxx.xxx的連接請求,開始通信…”,并等待客戶端輸入信息,讀入輸入流后(客戶端輸出的圓半徑值)后,進(jìn)行運(yùn)算,最后將結(jié)果通過輸出流發(fā)送給客戶端。運(yùn)行結(jié)果如圖10-3所示。

在MyClient.java中創(chuàng)建一個(gè)Socket對象,其IP地址為本機(jī)IP,端口號與服務(wù)器端的端口號8080相同,客戶端從鍵盤讀取輸入數(shù)據(jù)后,經(jīng)輸出流輸出圓的直徑值,傳遞給服務(wù)器端進(jìn)行運(yùn)算,客戶端skt對象的輸入流接收來自服務(wù)器的圓面積運(yùn)算結(jié)果,然后輸出。運(yùn)行結(jié)果如圖10-4所示。圖10-3服務(wù)器端運(yùn)行

圖10-4客戶端運(yùn)行上述服務(wù)器端程序只能接收單個(gè)客戶的連接請求,若為多個(gè)用戶提供連接,則需為每個(gè)客戶在連接時(shí)創(chuàng)建一個(gè)線程,可結(jié)合多線程程序來改造上述程序,詳細(xì)程序略,可參考相關(guān)資料。

UDP(UserDatagramProtocol,用戶數(shù)據(jù)報(bào)協(xié)議)是一種簡單的協(xié)議,可以實(shí)現(xiàn)快速的數(shù)據(jù)傳輸,它是一種面向無連接的通信,雖然定義了數(shù)據(jù)報(bào)的傳送,但不保證數(shù)據(jù)傳送的順序、丟包等,其可靠性較差。TCP協(xié)議是基于數(shù)據(jù)流的方式來實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)?,而UDP協(xié)議基于數(shù)據(jù)報(bào)傳輸數(shù)據(jù)。其到達(dá)的時(shí)間、內(nèi)容是否完整不得而知,因此一般比較適宜在網(wǎng)絡(luò)速度要求高而可靠性要求不高的場合,如網(wǎng)絡(luò)上的DNS域名解析服務(wù)(53端口)就是通過UDP協(xié)議來實(shí)現(xiàn)的。10.3數(shù)據(jù)報(bào)UDP編程在包中有兩個(gè)類DatagramSocket和DatagramPacket,用于實(shí)現(xiàn)UDP網(wǎng)絡(luò)通信程序設(shè)計(jì)。應(yīng)用DategramPacket類來創(chuàng)建UDP的數(shù)據(jù)報(bào),用DatagramSocket類來創(chuàng)建服務(wù)器端和客戶端的數(shù)據(jù)報(bào)套接字。

數(shù)據(jù)報(bào)根據(jù)用途可分為兩種:發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。接收數(shù)據(jù)報(bào)的構(gòu)造方法有publicDatagramPacket(byte[]buf,intlength)和DatagramPacket(byte[]buf,intoffset,intlength)。其中,參數(shù)buf用來指定接收內(nèi)容存儲在字節(jié)數(shù)組buf中,length為長度,offset為偏移值。如:

byte[]buffer=newbyte[8912];

DatagramPacketdatap=new

DatagramPacket(buffer,buffer.length());發(fā)送數(shù)據(jù)報(bào)的構(gòu)造方法有publicDatagramPacket(byte[]buf,intlength,InetAddressaddress,intport)和publicDatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport)。發(fā)送數(shù)據(jù)報(bào)不但要指定發(fā)送的字節(jié)數(shù)組buf和長度,同時(shí)還要指定發(fā)送數(shù)據(jù)報(bào)的地址和端口號。如:

try{

InetAddressserver=InetAddress.getByName("22");

intport=53;

Stringstr="Thisisatest";byte[]data=str.getBytes();

DatagramPacketoutgoing=newDatagramPacket(data,data.length,server,port);

...

}catch(IOExceptione){...}應(yīng)用UDP發(fā)送或接收數(shù)據(jù)時(shí),需要?jiǎng)?chuàng)建數(shù)據(jù)報(bào)的套接字,創(chuàng)建數(shù)據(jù)報(bào)套接字由DatagramSocket方法來實(shí)現(xiàn),DatagramSocket既可以用在服務(wù)器端的套接字也可以用在客戶端的套接字上,其構(gòu)造方法有:publicDatagramSocket()、publicDatagramSocket(intport)和publicDatagramSocket(intport,InetAddressladdr),這三種方法都會顯示SocketException的異常。若有參數(shù)port,則指定port端口上的通信;否則系統(tǒng)自動(dòng)指定一個(gè)可用端口來創(chuàng)建套接字。套接字創(chuàng)建后通過send(DatagramPacketp)和receive(DatagramPacketp)來發(fā)送或接收一個(gè)數(shù)據(jù)報(bào),通信完成后調(diào)用close()方法關(guān)閉數(shù)據(jù)報(bào)套接字,并釋放系統(tǒng)資源。下面通過一個(gè)具體的例子,介紹實(shí)現(xiàn)UDP服務(wù)器和客戶機(jī)的編程方法。在例子中,服務(wù)器端的程序不間斷地監(jiān)聽本機(jī)端口,一旦收到客戶端發(fā)來的數(shù)據(jù)報(bào),就回應(yīng)一個(gè)簡單的信息以通知客戶已經(jīng)收到了數(shù)據(jù)報(bào);客戶端程序向服務(wù)器發(fā)送一個(gè)包含一個(gè)字符串的數(shù)據(jù)報(bào),同時(shí)告知服務(wù)器自己的地址及端口,以便服務(wù)器作出回應(yīng)。【例10-5】服務(wù)器端程序UDPServerThread.java。

//UDP服務(wù)器端程序

importjava.io.*;

import.*;

importjava.util.*;

class

UDPServerThreadextendsThread

{//啟動(dòng)服務(wù)器線程的主程序

privateDatagramPacketpacket;

privateDatagramSocketsocket;

staticfinalintsport=1777;

UDPServerThread(){

try

{//將Socket連接到本機(jī)的一個(gè)可用的端口上

socket=newDatagramSocket(sport);

System.out.println("Listeningonport:"+socket.getLocalPort());

}

catch(Exceptione)

{

System.out.println("Error:"+e);

}

}

publicvoidrun()

{//線程的主要操作

if(socket==null)return;

while(true)

{

try

{

InetAddressaddress;

intcport;

byte[]buf=newbyte[1000];

Strings=“Yourpacketisreceived”;

packet=newDatagramPacket(buf,buf.length); //生成一個(gè)接收數(shù)據(jù)報(bào)

socket.receive(packet); //接收數(shù)據(jù)報(bào)

Strings1=newString(packet.getData());

System.out.println(“Receivedfromclient:”+s1);

//打印數(shù)據(jù)報(bào)的內(nèi)容

address=packet.getAddress();

cport=packet.getPort(); //獲得數(shù)據(jù)報(bào)的源地址與端口

s.getBytes(0,s.length(),buf,0);

packet=newDatagramPacket(buf,buf.length,address,cport);

//生成發(fā)送的數(shù)據(jù)報(bào)

socket.send(packet);

//發(fā)送數(shù)據(jù)報(bào)給客戶

}

catch(Exceptione)

{

System.out.println("Error:"+e);

}

}

}

protectedvoidfinalize()

{

if(socket!=null)

{

socket.close();//關(guān)閉socket

System.out.println("SocketClosed.");

}

}

publicstaticvoidmain(String[]args)

{

UDPServerThreadserver=newUDPServerThread();

server.start();

}

}【例10-6】客戶端程序UDPclient.java。

//UDP客戶端程序

importjava.io.*;

import.*;

importjava.util.*;

classUDPclient

{

publicstaticvoidmain(String[]args)

{DatagramSocketsocket; //用于發(fā)送接收UDP

DatagramPacketpacket; //用于保存UDP

的內(nèi)容

InetAddressaddress;

intport;

byte[]buf=newbyte[1000];

Strings="Hello,server!";

if(args.length<3)

{

System.out.println

("輸入本地端口號,服務(wù)器名,服務(wù)器端口號");

System.exit(0);

}

try

{

socket=newDatagramSocket(Integer.parseInt(args[0]));

溫馨提示

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

評論

0/150

提交評論