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

下載本文檔

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

文檔簡介

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

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

10.5習(xí)題

10.1.1InetAdress類

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

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

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

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

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

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

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

try

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

catch(UnknownHostExceptionex)

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

【例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("主機名: "+addr1.getHostName()+"IP地址:"+addr1.getHostAddress()+"\n");

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

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

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

System.out.println(addr3);

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

}

}

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

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

protocol://host[:port]/path

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

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

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

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

URLurl=newURL(“”);

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

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

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

try

{URLu1=newURL(“”);

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

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

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+

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

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(“顯示遠程文件”);

f.setSize(500,300);

f.setVisible(true);

f.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);

}

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

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

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

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

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

import.*;

importjava.io.*;

publicclassMyServer

{

publicstaticvoidmain(String[]args)throwsIOException

{

ServerSocketserver=newServerSocket(8080);

try

{System.out.println

("服務(wù)器程序啟動,開始監(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ù)計算?(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的連接請求,開始通信…”,并等待客戶端輸入信息,讀入輸入流后(客戶端輸出的圓半徑值)后,進行運算,最后將結(jié)果通過輸出流發(fā)送給客戶端。運行結(jié)果如圖10-3所示。

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

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

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

數(shù)據(jù)報根據(jù)用途可分為兩種:發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。接收數(shù)據(jù)報的構(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ù)報的構(gòu)造方法有publicDatagramPacket(byte[]buf,intlength,InetAddressaddress,intport)和publicDatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport)。發(fā)送數(shù)據(jù)報不但要指定發(fā)送的字節(jié)數(shù)組buf和長度,同時還要指定發(fā)送數(shù)據(jù)報的地址和端口號。如:

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

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

importjava.io.*;

import.*;

importjava.util.*;

class

UDPServerThreadextendsThread

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

privateDatagramPacketpacket;

privateDatagramSocketsocket;

staticfinalintsport=1777;

UDPServerThread(){

try

{//將Socket連接到本機的一個可用的端口上

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); //生成一個接收數(shù)據(jù)報

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

Strings1=newString(packet.getData());

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

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

address=packet.getAddress();

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

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

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

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

socket.send(packet);

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

}

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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論