復(fù)習(xí)課件13java網(wǎng)絡(luò)編程第16章_第1頁(yè)
復(fù)習(xí)課件13java網(wǎng)絡(luò)編程第16章_第2頁(yè)
復(fù)習(xí)課件13java網(wǎng)絡(luò)編程第16章_第3頁(yè)
復(fù)習(xí)課件13java網(wǎng)絡(luò)編程第16章_第4頁(yè)
復(fù)習(xí)課件13java網(wǎng)絡(luò)編程第16章_第5頁(yè)
已閱讀5頁(yè),還剩50頁(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)介

第16章網(wǎng)絡(luò)功能湖南工業(yè)大學(xué)計(jì)算機(jī)系滿(mǎn)君豐2第16章網(wǎng)絡(luò)功能16.1Java與internet16.2使用URL16.3訪(fǎng)問(wèn)cgi16.4URL連接16.5Socket16.6簡(jiǎn)單的Client/Server程序設(shè)計(jì)16.7支持多客戶(hù)的Client/Server程序設(shè)計(jì)16.8數(shù)據(jù)報(bào)16.9小結(jié)3第16章網(wǎng)絡(luò)功能網(wǎng)絡(luò)編程的目的就是指直接或間接地通過(guò)網(wǎng)絡(luò)協(xié)議與其他計(jì)算機(jī)進(jìn)行通訊。網(wǎng)絡(luò)編程中有兩個(gè)主要的問(wèn)題,一個(gè)是如何準(zhǔn)確的定位網(wǎng)絡(luò)上一臺(tái)或多臺(tái)主機(jī),另一個(gè)就是找到主機(jī)后如何可靠高效的進(jìn)行數(shù)據(jù)傳輸。在TCP/IP協(xié)議中IP層主要負(fù)責(zé)網(wǎng)絡(luò)主機(jī)的定位,數(shù)據(jù)傳輸?shù)穆酚?,由IP地址可以唯一地確定Internet上的一臺(tái)主機(jī)。而TCP層則提供面向應(yīng)用的可靠的或非可靠的數(shù)據(jù)傳輸機(jī)制,這是網(wǎng)絡(luò)編程的主要對(duì)象,一般不需要關(guān)心IP層是如何處理數(shù)據(jù)的。

目前較為流行的網(wǎng)絡(luò)編程模型是客戶(hù)機(jī)/服務(wù)器(C/S)結(jié)構(gòu)。即通信雙方一方作為服務(wù)器等待客戶(hù)提出請(qǐng)求并予以響應(yīng)??蛻?hù)則在需要服務(wù)時(shí)向服務(wù)器提出申請(qǐng)。服務(wù)器一般作為守護(hù)進(jìn)程始終運(yùn)行,監(jiān)聽(tīng)網(wǎng)絡(luò)端口,一旦有客戶(hù)請(qǐng)求,就會(huì)啟動(dòng)一個(gè)服務(wù)進(jìn)程來(lái)響應(yīng)該客戶(hù),同時(shí)自己繼續(xù)監(jiān)聽(tīng)服務(wù)端口,使后來(lái)的客戶(hù)也能及時(shí)得到服務(wù)。4第16章網(wǎng)絡(luò)功能IP地址:標(biāo)識(shí)計(jì)算機(jī)等網(wǎng)絡(luò)設(shè)備的網(wǎng)絡(luò)地址,由四個(gè)8位的二進(jìn)制數(shù)組成,中間以小數(shù)點(diǎn)分隔。

如:,0

主機(jī)名(hostname):網(wǎng)絡(luò)地址的助記名,按照域名進(jìn)行分級(jí)管理。

如:

端口號(hào)(portnumber):網(wǎng)絡(luò)通信時(shí)同一機(jī)器上的不同進(jìn)程的標(biāo)識(shí)。

如:80,21,23,25,其中1~1024為系統(tǒng)保留的端口號(hào)

服務(wù)類(lèi)型(service):網(wǎng)絡(luò)的各種服務(wù)。

http,telnet,ftp,smtp

5第16章網(wǎng)絡(luò)功能在Internet上IP地址和主機(jī)名是一一對(duì)應(yīng)的,通過(guò)域名解析可以由主機(jī)名得到機(jī)器的IP,由于機(jī)器名更接近自然語(yǔ)言,容易記憶,所以使用比IP地址廣泛,但是對(duì)機(jī)器而言只有IP地址才是有效的標(biāo)識(shí)符。

通常一臺(tái)主機(jī)上總是有很多個(gè)進(jìn)程需要網(wǎng)絡(luò)資源進(jìn)行網(wǎng)絡(luò)通訊。網(wǎng)絡(luò)通訊的對(duì)象準(zhǔn)確的講不是主機(jī),而應(yīng)該是主機(jī)中運(yùn)行的進(jìn)程。這時(shí)候光有主機(jī)名或IP地址來(lái)標(biāo)識(shí)這么多個(gè)進(jìn)程顯然是不夠的。端口號(hào)就是為了在一臺(tái)主機(jī)上提供更多的網(wǎng)絡(luò)資源而采取得一種手段,也是TCP層提供的一種機(jī)制。只有通過(guò)主機(jī)名或IP地址和端口號(hào)的組合才能唯一的確定網(wǎng)絡(luò)通訊中的對(duì)象:進(jìn)程。

6第16章網(wǎng)絡(luò)功能

TCP是TranferControlProtocol的簡(jiǎn)稱(chēng),是一種面向連接的保證可靠傳輸?shù)膮f(xié)議。通過(guò)TCP協(xié)議傳輸,得到的是一個(gè)順序的無(wú)差錯(cuò)的數(shù)據(jù)流。發(fā)送方和接收方的成對(duì)的兩個(gè)socket之間必須建立連接,以便在TCP協(xié)議的基礎(chǔ)上進(jìn)行通信,當(dāng)一個(gè)socket(通常都是serversocket)等待建立連接時(shí),另一個(gè)socket可以要求進(jìn)行連接,一旦這兩個(gè)socket連接起來(lái),它們就可以進(jìn)行雙向數(shù)據(jù)傳輸,雙方都可以進(jìn)行發(fā)送或接收操作。

UDP是UserDatagramProtocol的簡(jiǎn)稱(chēng),是一種無(wú)連接的協(xié)議,每個(gè)數(shù)據(jù)報(bào)都是一個(gè)獨(dú)立的信息,包括完整的源地址或目的地址,它在網(wǎng)絡(luò)上以任何可能的路徑傳往目的地,因此能否到達(dá)目的地,到達(dá)目的地的時(shí)間以及內(nèi)容的正確性都是不能被保證的。716.1Java與網(wǎng)絡(luò)Java語(yǔ)言取得成功的領(lǐng)域之一就是網(wǎng)絡(luò)

(其他語(yǔ)言)數(shù)頁(yè)代碼---->(Java)一條語(yǔ)句TCP/IP(傳輸控制協(xié)議/網(wǎng)間協(xié)議)是internet的主要協(xié)議,定義了計(jì)算機(jī)和外設(shè)進(jìn)行通信所使用的規(guī)則(應(yīng)用層,傳輸層,網(wǎng)絡(luò)層,鏈路層).大多數(shù)基于internet的應(yīng)用程序被看作TCP/IP協(xié)議的上一層.如:ftp,http,smtp,pop3,telnet,nntp等IP地址:TCP/IP網(wǎng)絡(luò)中的每臺(tái)計(jì)算機(jī)都有唯一的地址--IP地址.在Java中,有一個(gè)用來(lái)存儲(chǔ)internet地址的類(lèi)叫InetAddress.816.1Java與網(wǎng)絡(luò)例:獲取本機(jī)的IP地址import.*;publicclassgetLocalHostTest{publicstaticvoidmain(){InetAddressmyIP=null;try{myIP=InetAddress.getLocalHost();}catch(Exceptione){e.printStackTrace();}System.out.println(myIP);}}創(chuàng)建inetAddress類(lèi)不用構(gòu)造函數(shù)(不用new)916.1Java與網(wǎng)絡(luò)下面的例子演示java如何根據(jù)域名自動(dòng)到DNS上查找IP地址(與DNS服務(wù)器的連接減至一行)import.*;publicclassgetIP{publicstaticvoidmain(Stringargs[]){InetAddresszhuzit=null;try{zhuzit=InetAddress.getByName(“”);}catch(UnknowHostExceptione){}System.out.println(zhuzit);}}運(yùn)行結(jié)果:1016.1Java與網(wǎng)絡(luò)

一個(gè)URL對(duì)象生成后,其屬性是不能被改變的,但是我們可以通過(guò)類(lèi)URL所提供的方法來(lái)獲取這些屬性:

publicStringgetProtocol()獲取該URL的協(xié)議名。

publicStringgetHost()獲取該URL的主機(jī)名。

publicintgetPort()獲取該URL的端口號(hào),如果沒(méi)有設(shè)置端口,返回-1。

publicStringgetFile()獲取該URL的文件名。

publicStringgetRef()獲取該URL在文件中的相對(duì)位置。

publicStringgetQuery()獲取該URL的查詢(xún)信息。

publicStringgetPath()獲取該URL的路徑

publicStringgetAuthority()獲取該URL的權(quán)限信息

publicStringgetUserInfo()獲得使用者的信息

publicStringgetRef()獲得該URL的錨1116.1Java與網(wǎng)絡(luò)import.*;

importjava.io.*;publicclassParseURL{

publicstaticvoidmain(String[]args)throwsException{URLAurl=newURL("");

URLtuto=newURL(Aurl,"ro.html#DOWNLOADING");

System.out.println("protocol="+tuto.getProtocol());

System.out.println("host="+tuto.getHost());

System.out.println("filename="+tuto.getFile());

System.out.println("port="+tuto.getPort());

System.out.println("ref="+tuto.getRef());

System.out.println("query="+tuto.getQuery());

System.out.println("path="+tuto.getPath());

System.out.println("UserInfo="+tuto.getUserInfo());

System.out.println("Authority="+tuto.getAuthority());

}

}

1216.1Java與網(wǎng)絡(luò)執(zhí)行結(jié)果為:

protocol=httphostfilename=/docs/books/ro.htmlport=80ref=DOWNLOADINGquery=nullpath=/docs/books/ro.htmlUserInfo=nullAuthority:801316.1Java與網(wǎng)絡(luò)Java提供的網(wǎng)絡(luò)功能有三大類(lèi):URL,Socket,Datagram.URL是三大功能中最高級(jí)的一種,通過(guò)URLJava程序可以直接送出或讀入網(wǎng)絡(luò)上的數(shù)據(jù).Socket是傳統(tǒng)網(wǎng)絡(luò)程序最常用的方式,可以想象為兩個(gè)不同的程序通過(guò)網(wǎng)絡(luò)的通信信道.Datagram是更低級(jí)的網(wǎng)絡(luò)傳輸方式,它把數(shù)據(jù)的目的紀(jì)錄在數(shù)據(jù)包中,然后直接放在網(wǎng)絡(luò)上.※

1416.2使用URL當(dāng)我們得到一個(gè)URL對(duì)象后,就可以通過(guò)它讀取指定的WWW資源。這時(shí)我們將使用URL的方法openStream(),其定義為:InputStreamopenStream();

方法openSteam()與指定的URL建立連接并返回InputStream類(lèi)的對(duì)象以從這一連接中讀取數(shù)據(jù)。publicclassURLReader{publicstaticvoidmain(String[]args)throwsException{//聲明拋出所有例外URLtirc=newURL("");//構(gòu)建一URL對(duì)象BufferedReaderin=newBufferedReader(newInputStreamReader(tirc.openStream()));//使用openStream得到一輸入流并由此構(gòu)造一個(gè)BufferedReader對(duì)象StringinputLine;while((inputLine=in.readLine())!=null)//從輸入流不斷的讀數(shù)據(jù),直到讀完為止System.out.println(inputLine);//把讀入的數(shù)據(jù)打印到屏幕上in.close();//關(guān)閉輸入流}}

1516.2使用URLprotocol://resourceName

協(xié)議名(protocol)指明獲取資源所使用的傳輸協(xié)議,如http、ftp、gopher、file等,資源名(resourceName)則應(yīng)該是資源的完整地址,包括主機(jī)名、端口號(hào)、文件名或文件內(nèi)部的一個(gè)引用。例如:

協(xié)議名://主機(jī)名

協(xié)議名://機(jī)器名+文件名

協(xié)議名://機(jī)器名+端口號(hào)+文件名+內(nèi)部引用

168.2使用URL例:從給定的位置中讀數(shù)據(jù)(ReadURLData.prj)

connect<html><head><title><...></title></head><body>

actionURLurlButtonFrame主類(lèi)str=a.getText()b=url.openStream()TextAreacline_str=b.readLine()c.appendText(line_str);TextFieldaURLurl=newURL(str)DataInputStreamb16.4URL連接URL雙向通信(URLConection)URLConnection是一個(gè)一http為中心的類(lèi)1.建立連接URLurl=newURL(“”);URLConnectioncon=url.openConnection();2.向服務(wù)器端送數(shù)據(jù)PrintStreamoutStream=newPrintStream(con.getOutputStream());outStream.println(string_data);16.4URL連接3.從服務(wù)器讀數(shù)據(jù)

DataInputStreaminStream=newDataInputStream(con.getInputStream());inStream.readLine();從URL中得到的輸出流通常與一個(gè)CGI程序結(jié)合一起工作客戶(hù)端java程序DataOutputStreamDataInputStreamCGI程序STDINSTDOUT服務(wù)器(排序

sort.cgi)connectiuongetchar()putchar()16.4URL連接URLConnection同時(shí)支持get和post兩種機(jī)制一般的格式.缺省情況下位postmethod方式URL和URLConnection的區(qū)別在于前者代表一個(gè)資源的位置,后者代表一種連接下面的例子中Java程序訪(fǎng)問(wèn)cgi程序,并傳給它10個(gè)數(shù)據(jù),cgi程序胡接收后,排序,并傳送回來(lái).連接的建立、數(shù)據(jù)流的建立、java如何發(fā)數(shù)據(jù)、如何接收數(shù)據(jù)、cgi程序如何發(fā)送和接收16.4URL連接Try{

URLnetchinaren=newURL("");

URLConnectonntc=netchinaren.openConnection();

}catch(MalformedURLExceptione){//創(chuàng)建URL()對(duì)象失敗

}catch(IOExceptione){//openConnection()失敗

}

類(lèi)URLConnection提供了很多方法來(lái)設(shè)置或獲取連接參數(shù),程序設(shè)計(jì)時(shí)最常使用的是getInputStream()和getOurputStream(),其定義為:

InputSteramgetInputSteram();

OutputSteramgetOutputStream();

16.4URL連接通過(guò)返回的輸入/輸出流我們可以與遠(yuǎn)程對(duì)象進(jìn)行通信。看下面的例子:

URLurl=newURL("");

//創(chuàng)建一URL對(duì)象

URLConnectincon=url.openConnection();

//由URL對(duì)象獲取URLConnection對(duì)象

DataInputStreamdis=newDataInputStream(con.getInputSteam());

//由URLConnection獲取輸入流,并構(gòu)造DataInputStream對(duì)象

PrintStreamps=newPrintSteam(con.getOutupSteam());

//由URLConnection獲取輸出流,并構(gòu)造PrintStream對(duì)象

Stringline=dis.readLine();//從服務(wù)器讀入一行

ps.println("client…");//向服務(wù)器寫(xiě)出字符串"client…"16.5Socket16.5.1什么是socket?Socket是網(wǎng)絡(luò)上運(yùn)行的程序之間雙向通信鏈路的最后終結(jié)點(diǎn)網(wǎng)絡(luò)服務(wù)Mailftpfinger20telnet數(shù)據(jù)結(jié)構(gòu)I/O緩沖區(qū)端口2123客戶(hù)程序SocketIP,portIP與端口的組合得出一個(gè)套接字,可以完全分辨internet上運(yùn)行的程序※

internet服務(wù)端口號(hào)端口號(hào)internet服務(wù)telnet23nntp119ftp21www80DNS53POP311016.5Socket端口號(hào):TCP/IP協(xié)議為每種服務(wù)定義了一個(gè)端口,當(dāng)一臺(tái)計(jì)算機(jī)上運(yùn)行不同服務(wù)器程序時(shí),根據(jù)端口號(hào)不同提供相應(yīng)的服務(wù).端口號(hào)不是計(jì)算機(jī)上的物理連接器,它只是具有軟件意義的假想端口16.5Socket在服務(wù)器端通過(guò)指定一個(gè)用來(lái)等待的連接的端口號(hào)創(chuàng)建一個(gè)ServerSocket實(shí)例.在客戶(hù)端通過(guò)規(guī)定一個(gè)主機(jī)和端口號(hào)創(chuàng)建一個(gè)socket實(shí)例,連到服務(wù)器上.ServerSocket類(lèi)的accept方法使服務(wù)器處于阻塞狀態(tài),等待用戶(hù)請(qǐng)求Socket類(lèi)和ServerSocket是基于TCP協(xié)議的,TCP協(xié)議提供64個(gè)端口,256以?xún)?nèi)位保留端口.16.5Socket在本地機(jī)器上測(cè)試網(wǎng)絡(luò)程序用回送地址Socketsocket=newSocket(“”,2525);如果網(wǎng)絡(luò)的一端已經(jīng)關(guān)閉,另一端讀到null.建立socket連接后,還應(yīng)該建立輸入輸出數(shù)據(jù)流.16.5SocketServerServerSocket(port#)ServerSocket.accept()Socket()OutputStreamInputStreamCloseSocketClientSocket(host,port#)AttempttheconnectionOutputStreamInputStreamCloseSocket使用Socket進(jìn)行Client/Server程序設(shè)計(jì)的一般連接過(guò)程是這樣的:Server端Listen(監(jiān)聽(tīng))某個(gè)端口是否有連接請(qǐng)求,Client端向Server端發(fā)出Connect(連接)請(qǐng)求,Server端向Client端發(fā)回Accept(接受)消息。一個(gè)連接就建立起來(lái)了。Server端和Client端都可以通過(guò)Send,Write等方法與對(duì)方通信?!?/p>

16.5Socket

對(duì)于一個(gè)功能齊全的Socket,都要包含以下基本結(jié)構(gòu),其工作過(guò)程包含以下四個(gè)基本的步驟:

1)創(chuàng)建Socket;

2)打開(kāi)連接到Socket的輸入/出流;

3)按照一定的協(xié)議對(duì)Socket進(jìn)行讀/寫(xiě)操作;

4)關(guān)閉Socket.

第三步是程序員用來(lái)調(diào)用Socket和實(shí)現(xiàn)程序功能的關(guān)鍵步驟,其他三步在各種程序中基本相同。

288.5Socket.8.5Socket創(chuàng)建服務(wù)器(端口號(hào))定義數(shù)據(jù)成員服務(wù)器等待網(wǎng)絡(luò)連接建立socket流讀客戶(hù)端信息向用戶(hù)發(fā)出一個(gè)字符串創(chuàng)建Socket實(shí)例定義數(shù)據(jù)成員建立socket流讀socket流(接收并顯示)送用戶(hù)名給服務(wù)器關(guān)閉流waitingforuser11111111login:connetctingclient...java提示用戶(hù)登錄成功讀socket流User:javaLoginsuccessful298.5Socket例:顯示服務(wù)器與客戶(hù)機(jī)間的通信(服務(wù)器端)PrintStreamps=null;DataInputStreamdis=null;Stringusername;ServerSocketserverSocket=null;SocketclientSocket=null;try{serverSocket=newServerSocket(1111);}catch(IOExceptione){System.out.println(“Error”+e);System.exit(1);}try{clientSocket=serverSocket.accept();}catch(IOExceptione){System.out.println("Acceptfailed.");System.exit(1);}創(chuàng)建服務(wù)器(端口號(hào))定義數(shù)據(jù)成員服務(wù)器等待網(wǎng)絡(luò)連接16.5Socketps=newPrintStream(clientSocket.getOutputStream());dis=newDataInputStream(clientSocket.getInputStream());創(chuàng)建服務(wù)器(端口號(hào))定義數(shù)據(jù)成員服務(wù)器等待網(wǎng)絡(luò)連接建立socket流向客戶(hù)發(fā)出登錄要求ps.println("login:");ps.flush();16.5Socketps.println("loginsucessful");ps.flush();System.out.println(username+"hasloggedoff");}讀客戶(hù)端信息創(chuàng)建服務(wù)器(端口號(hào))定義數(shù)據(jù)成員服務(wù)器等待網(wǎng)絡(luò)連接建立socket流向用戶(hù)發(fā)出登錄要求通知客戶(hù)連接完畢if((username=dis.readLine())==null){ System.out.println("readLinereturnednull"); System.exit(1);}System.out.println("Username:"+username);16.5Socket例:顯示服務(wù)器與客戶(hù)機(jī)間的通信(客戶(hù)端)創(chuàng)建Socket實(shí)例PrintStreamoutput;DataInputStreaminput;Stringstring; Socketsocket=null;定義數(shù)據(jù)成員try{socket=newSocket("",1111);}catch(IOExceptione){System.out.println("Error”+e);return;}

input=newDataInputStream(socket.getInputStream());output=newPrintStream(socket.getOutputStream());

建立socket流16.5Socket.System.out.println(input.readLine());創(chuàng)建Socket實(shí)例定義數(shù)據(jù)成員建立socket流讀socket流(看到提示)System.in.read(bArray);Strings=newString(bArray,0);output.println(s);從鍵盤(pán)上讀送用戶(hù)名送給服務(wù)器端關(guān)閉流socket.close();input.close();output.close();System.out.println("Done");System.out.println(input.readLine());System.out.print("Loggingoff...");讀服務(wù)器反饋34.8.5Socket.8.5Socket創(chuàng)建服務(wù)器(端口號(hào))定義數(shù)據(jù)成員服務(wù)器等待網(wǎng)絡(luò)連接建立socket流讀客戶(hù)端信息向用戶(hù)發(fā)送字符串創(chuàng)建Socket實(shí)例定義數(shù)據(jù)成員建立socket流讀socket流(看到提示)送用戶(hù)名給服務(wù)器關(guān)閉流waitingforuser11111111login:connetctingclient...java提示用戶(hù)登錄成功讀socket流User:javaLoginsuccessful16.6簡(jiǎn)單的Client/Server程序設(shè)計(jì)客戶(hù)端程序

importjava.io.*;

import.*;

publicclassTalkClient{

publicstaticvoidmain(Stringargs[]){

try{

Socketsocket=newSocket("",4700);

//向本機(jī)的4700端口發(fā)出客戶(hù)請(qǐng)求

BufferedReadersin=newBufferedReader(newInputStreamReader(System.in));

//由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對(duì)象

PrintWriteros=newPrintWriter(socket.getOutputStream());

//由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象

BufferedReaderis=newBufferedReader(newInputStreamReader(socket.getInputStream()));

//由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象

Stringreadline;

readline=sin.readLine();//從系統(tǒng)標(biāo)準(zhǔn)輸

16.6簡(jiǎn)單的Client/Server程序設(shè)計(jì)客戶(hù)端程序

while(!readline.equals("bye")){

//若從標(biāo)準(zhǔn)輸入讀入的字符串為"bye"則停止循環(huán)

os.println(readline);

//將從系統(tǒng)標(biāo)準(zhǔn)輸入讀入的字符串輸出到Server

os.flush();

//刷新輸出流,使Server馬上收到該字符串

System.out.println("Client:"+readline);

//在系統(tǒng)標(biāo)準(zhǔn)輸出上打印讀入的字符串

System.out.println("Server:"+is.readLine());

//從Server讀入一字符串,并打印到標(biāo)準(zhǔn)輸出上

readline=sin.readLine();//從系統(tǒng)標(biāo)準(zhǔn)輸入讀入一字符串

}//繼續(xù)循環(huán)

os.close();//關(guān)閉Socket輸出流

is.close();//關(guān)閉Socket輸入流

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

}catch(Exceptione){

System.out.println("Error"+e);//出錯(cuò),則打印出錯(cuò)信息

}

}

}16.6簡(jiǎn)單的Client/Server程序設(shè)計(jì)服務(wù)器端程序

importjava.io.*;

import.*;

importjava.applet.Applet;

publicclassTalkServer{

publicstaticvoidmain(Stringargs[]){

try{

ServerSocketserver=null;

try{

server=newServerSocket(4700);

//創(chuàng)建一個(gè)ServerSocket在端口4700監(jiān)聽(tīng)客戶(hù)請(qǐng)求

}catch(Exceptione){

System.out.println(“cannotlistento:”+e);

//出錯(cuò),打印出錯(cuò)信息

}Socketsocket=null;

try{

socket=server.accept();

//使用accept()阻塞等待客戶(hù)請(qǐng)求,有客戶(hù)

//請(qǐng)求到來(lái)則產(chǎn)生一個(gè)Socket對(duì)象,并繼續(xù)執(zhí)行

}catch(Exceptione){

System.out.println(“Error.”+e);

//出錯(cuò),打印出錯(cuò)信息

}

16.6簡(jiǎn)單的Client/Server程序設(shè)計(jì)服務(wù)器端程序

Stringline;

BufferedReaderis=newBufferedReader(newInputStreamReader(socket.getInputStream()));

//由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象

PrintWriteros=newPrintWriter(socket.getOutputStream());

//由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象

BufferedReadersin=newBufferedReader(newInputStreamReader(System.in));

//由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對(duì)象

System.out.println(“Client:”+is.readLine());

//在標(biāo)準(zhǔn)輸出上打印從客戶(hù)端讀入的字符串

line=sin.readLine();

//從標(biāo)準(zhǔn)輸入讀入一字符串

while(!line.equals(“bye”)){

//如果該字符串為“bye”,則停止循環(huán)

os.println(line);

//向客戶(hù)端輸出該字符串

os.flush();

//刷新輸出流,使Client馬上收到該字符串

System.out.println(“Server:”+line);

//在系統(tǒng)標(biāo)準(zhǔn)輸出上打印讀入的字符串

System.out.println(“Client:”+is.readLine());//從Client讀入一字符串,并打印到標(biāo)準(zhǔn)輸出上

line=sin.readLine();

//從系統(tǒng)標(biāo)準(zhǔn)輸入讀入一字符串

}

//繼續(xù)循環(huán)

os.close();//關(guān)閉Socket輸出流

is.close();//關(guān)閉Socket輸入流

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

server.close();//關(guān)閉ServerSocket

}catch(Exceptione){

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

//出錯(cuò),打印出錯(cuò)信息

}

}

}

16.7支持多客戶(hù)的Client/Server程序設(shè)計(jì)前面提供的Client/Server程序只能實(shí)現(xiàn)Server和一個(gè)客戶(hù)的對(duì)話(huà)。在實(shí)際應(yīng)用中,往往是在服務(wù)器上運(yùn)行一個(gè)永久的程序,它可以接收來(lái)自其他多個(gè)客戶(hù)端的請(qǐng)求,提供相應(yīng)的服務(wù)。為了實(shí)現(xiàn)在服務(wù)器方給多個(gè)客戶(hù)提供服務(wù)的功能,需要對(duì)上面的程序進(jìn)行改造,利用多線(xiàn)程實(shí)現(xiàn)多客戶(hù)機(jī)制。服務(wù)器總是在指定的端口上監(jiān)聽(tīng)是否有客戶(hù)請(qǐng)求,一旦監(jiān)聽(tīng)到客戶(hù)請(qǐng)求,服務(wù)器就會(huì)啟動(dòng)一個(gè)專(zhuān)門(mén)的服務(wù)線(xiàn)程來(lái)響應(yīng)該客戶(hù)的請(qǐng)求,而服務(wù)器本身在啟動(dòng)完線(xiàn)程之后馬上又進(jìn)入監(jiān)聽(tīng)狀態(tài),等待下一個(gè)客戶(hù)的到來(lái)。

客戶(hù)端的程序和上面程序是完全一樣的,讀者如果仔細(xì)閱讀過(guò)上面的程序,可以跳過(guò)不讀,把主要精力集中在Server端的程序上?!?/p>

16.7支持多客戶(hù)的Client/Server程序設(shè)計(jì)16.7支持多客戶(hù)的Client/Server程序設(shè)計(jì)服務(wù)器端程序:MultiTalkServer.java

importjava.io.*;

import.*;

importServerThread;

publicclassMultiTalkServer{

staticintclientnum=0;//靜態(tài)成員變量,記錄當(dāng)前客戶(hù)的個(gè)數(shù)

publicstaticvoidmain(Stringargs[])throwsIOException{

ServerSocketserverSocket=null;

booleanlistening=true;

try{

serverSocket=newServerSocket(4700);

//創(chuàng)建一個(gè)ServerSocket在端口4700監(jiān)聽(tīng)客戶(hù)請(qǐng)求

}catch(IOExceptione){

System.out.println(“Couldnotlistenonport:4700.”);//出錯(cuò),打印出錯(cuò)信息

System.exit(-1);//退出

}

while(listening){//永遠(yuǎn)循環(huán)監(jiān)聽(tīng)

newServerThread(serverSocket.accept(),clientnum).start();

//監(jiān)聽(tīng)到客戶(hù)請(qǐng)求,根據(jù)得到的Socket對(duì)象和客戶(hù)計(jì)數(shù)創(chuàng)建服務(wù)線(xiàn)程,并啟動(dòng)之

clientnum++;//增加客戶(hù)計(jì)數(shù)

}

serverSocket.close();//關(guān)閉ServerSocket

}

}※

16.7支持多客戶(hù)的Client/Server程序設(shè)計(jì)程序ServerThread.java

importjava.io.*;

import.*;

publicclassServerThreadextendsThread{

Socketsocket=null;//保存與本線(xiàn)程相關(guān)的Socket對(duì)象

intclientnum;//保存本進(jìn)程的客戶(hù)計(jì)數(shù)

publicServerThread(Socketsocket,intnum){//構(gòu)造函數(shù)

this.socket=socket;//初始化socket變量

clientnum=num+1;//初始化clientnum變量

}

publicvoidrun(){//線(xiàn)程主體

try{

Stringline;

BufferedReaderis=newBufferedReader(newInputStreamReader(socket.getInputStream()));

//由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象

PrintWriteros=newPrintWriter(socket.getOutputStream());

//由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象

BufferedReadersin=newBufferedReader(newInputStreamReader(System.in));

//由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對(duì)象

System.out.println("Client:"+clientnum+is.readLine());

//在標(biāo)準(zhǔn)輸出上打印從客戶(hù)端讀入的字符串

line=sin.readLine();

//從標(biāo)準(zhǔn)輸入讀入一字符串

16.7支持多客戶(hù)的Client/Server程序設(shè)計(jì)

while(!line.equals("bye")){

//如果該字符串為"bye",則停止循環(huán)

os.println(line);

//向客戶(hù)端輸出該字符串

os.flush();

//刷新輸出流,使Client馬上收到該字符串

System.out.println("Server:"+line);

//在系統(tǒng)標(biāo)準(zhǔn)輸出上打印該字符串

System.out.println("Client:"+clientnum+is.readLine());

//從Client讀入一字符串,并打印到標(biāo)準(zhǔn)輸出上

line=sin.readLine();

//從系統(tǒng)標(biāo)準(zhǔn)輸入讀入一字符串

}//繼續(xù)循環(huán)

os.close();//關(guān)閉Socket輸出流

is.close();//關(guān)閉Socket輸入流

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

server.close();//關(guān)閉ServerSocket

}catch(Exceptione){

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

//出錯(cuò),打印出錯(cuò)信息

}

}

}

16.8DatagramTCP/IP傳輸層由兩個(gè)并列的協(xié)議:TCP,UDP.一般套接字(TCP)提供一個(gè)可靠的傳輸模型作為兩個(gè)網(wǎng)絡(luò)端點(diǎn)的字節(jié)流,有糾錯(cuò)能力.UDP沒(méi)有保持的連接和數(shù)據(jù)流,數(shù)據(jù)報(bào)是一個(gè)網(wǎng)絡(luò)上發(fā)送的獨(dú)立信息,它的到達(dá),到達(dá)時(shí)間,以及內(nèi)容不能得到保證.socketserverclientdatagramserverclient16.8DatagramTCP提供高可靠性服務(wù),適用于一次要傳輸交換大量報(bào)文的情況,信道上傳遞的包不需要源地址和目的地址UDP提供高效率服務(wù),適用于依次傳輸交換少量報(bào)文的情形(如數(shù)據(jù)庫(kù)查詢(xún)),每個(gè)數(shù)據(jù)包要包含目的地址和端口號(hào).數(shù)據(jù)報(bào)文的使用以包為中心:打包,拆包.包支持兩種不同的在網(wǎng)絡(luò)上送數(shù)據(jù)的方法:一般套接字和數(shù)據(jù)報(bào)文套接字.16.8Datagram發(fā)出報(bào)文的標(biāo)準(zhǔn)步驟如下:1.定義數(shù)據(jù)成員DatagramSocketsocket;DatagramPacketpacket;InetAddressaddress;(用來(lái)存放接收方的地址)intport;;(用來(lái)存放接收方的端口號(hào))2.創(chuàng)建數(shù)據(jù)報(bào)文Socket對(duì)象try{socket=newDatagramSocket(1111);}c

溫馨提示

  • 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)論