




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
在線教務輔導網:教材其余課件及動畫素材請查閱在線教務輔導網QQ:349134187或者直接輸入下面地址:1在線教務輔導網:http://www.shangfuwang7/28/20232作者:肖明學校:煙臺大學計算機學院日期:2010年2月第四章
JAVA網路編程7/28/20232作者:肖明第四章
JAVA網路編程第四章JAVA網絡編程4.1數據流4.2基于TCP協議的套接字通信4.1數據流4.4組播套接字4.5小結習題四3第四章JAVA網絡編程4.1數據流3第四章JAVA網絡編程Java的基于TCP/IP協議的客戶端與服務器模式下的網絡編程原理,涉及到的類主要有兩個包:輸入輸出包:java.io網絡包:。4第四章JAVA網絡編程Java的基于TCP/IP協議的客戶4.1數據流當前網絡通信,都是由數據流(datastream)來處理的,因此,基于流通信(stream-basedcommunication)是Java網絡編程的基礎。數據流:是發送和接收信息的管道或通道,當數據通信管道建立起來,數據就可以從管道的一端傳輸到另一端。通信:是指在管道中流動的數據過程,這種數據流通信是以字節為基本數據單位,通過串行形式的數據序列順序進行傳輸的過程。4.1.1數據流與網絡技術的聯系4.1.2流的工作方式4.1.3過濾器流、讀取器和寫入器4.1.4對象持久性和對象序列化54.1數據流當前網絡通信,都是由數據流(datastre4.1.1數據流與網絡技術的聯系網絡技術使得物理網絡連通,在有效的協議控制下,實現信息傳輸,即套接字Socket的連接和通信。網絡編程:是基于這種連通和相關協議控制下的套接字Socket實現網絡的底層連接,再以流(stream)為類的操作,進行數據傳輸和流的關閉等。從另一個角度看,流為網絡通信提供了統一的接口,使得網絡通信更加規范和一致。64.1.1數據流與網絡技術的聯系網絡技術使得物理網絡連通4.1.1數據流與網絡技術的聯系在Java中,是以流(也就是類)來表示網絡上的數據、文件或應用程序之間的通信。流劃分為兩種:輸入流(inputstream):將數據從某個數據源發送到程序中;輸出流(outputstream):將數據從程序中往外發送到某個目地端。輸入、輸出流的劃分,極大地方便了編程。可以靈活地,分別獨立地從輸入流中讀數據,接受數據,向輸出流中寫數據,發送數據,實現單向(one-way)或雙向(two-way)通訊等。74.1.1數據流與網絡技術的聯系在Java中,是以流(也4.1.2流的工作方式在Java中,流是以字節級進行數據通信,為此分別提供了:字節輸入流公用超類java.io.InputStream字節輸出流公用超類java.io.OutputStream都是抽象類,也是基礎性的底層字節輸入輸出類(流)。定義了公共的公有方法,通過兩級子類繼承,來實現這些方法和子類自己的方法。
84.1.2流的工作方式在Java中,流是以字節級進行數據兩級子類繼承字節輸入、輸出流公用超類繼承關系一級子類FilterInputStreamInputStreamFilterOutputStreamOutputStreamDataInputStreamDataOutputStreamBufferedInputStreamBufferedOutputStreamDataInputDataOutputObject字節輸出流接口ObjectInputStream……圖4.1字節輸入、輸出流公用超類繼承關系…………字節輸入流過濾輸入流過濾輸出流公用超類二級子類數據輸入流數據輸出流緩沖輸入流緩沖輸出流ObjectOutputStream……9兩級子類繼承字節輸入、輸出流公用超類繼承關系一級子類Fil第一級繼承有4或6個子類不等,其中數據源包括:字節數組(ByteArray)字符串(String)文件(File)管道(Pipe)過濾器(Filter)其他等數據源與網絡通信有關的InputStream和OutputStream的子類是:過濾器輸入流FilterInputStream過濾器輸出流FilterOutputStream這兩個類也是抽象類10第一級繼承有4或6個子類不等,其中數據源包括:與網絡通信有關第二級繼承在過濾器流的基礎上繼承,有10或8個子類,基本上都與網絡通信有關,其中常用的是:過濾器輸入流FilterInputStream的子類:數據輸入流DataInputStream緩沖輸入流BufferedInputStream數據輸入流接口DataInput;過濾器輸出流FilterOutputStream的子類:數據輸出流DataOutputStream緩沖輸出流BufferedOutputStream數據輸出流接口DataOutput;11第二級繼承在過濾器流的基礎上繼承,有10或8個子類,基本上都與網絡通信有關的流工作方式指創建過濾器輸入流子類或過濾器輸出流子類與套接字通信綁定的對象方式。有了這些流對象就可以調用其方法完成底層字節流的套接字網絡數據通信。在具體設計上是兩個程序,分別裝在網絡上的兩臺計算機上。在互聯網上,有三種模式:點對點的P2P(peer-to-peer)模式,又稱對等互聯網絡技術,客戶端和服務器(C/S)體系結構瀏覽器和服務器(B/S)體系結構12與網絡通信有關的流工作方式指創建過濾器輸入流子類或過濾器輸出4.1.3過濾器流、讀取器和寫入器過濾器流具有緩沖區的過濾器流BufferedInputStream和BufferedOutputStream流對數據訪問時可提高效率。訪問不同數據類型的過濾器流DataInputStream和DataOutputStream流提供了訪問各種不同數據類型的方法過濾器流的特點在進行讀寫數據的同時,還可進行數據處理,方便了網絡編程。134.1.3過濾器流、讀取器和寫入器過濾器流13讀取器Reader和寫入器Writer它們均為IO包中的類,都是抽象的公用超類。它們也是通過其子類繼承實現讀入和寫出。不同點是讀寫器以字符流操作應用程序以字符形式輸入和輸出速度更快、功能更強,但需要將字符轉換成字節來實現網絡通信。14讀取器Reader和寫入器Writer它們均為IO包中的類,1.過濾器流指過濾器輸入流FilterInputStream和過濾器輸出流FilterOutputStream,這兩個抽象類,以及所對應的子類。過濾器輸入流FilterInputStream,通過其子類繼承實現輸入流操作,共有10個子類:151.過濾器流指過濾器輸入流FilterInputStream過濾器輸入流FilterInputStream的子類⑴數據輸入流DataInputStream定義:publicclassDataInputStreamextendsFilterInputStreamimplementsDataInput構造函數:DataInputStream(InputStreamin)方法如下:intread(byte[]b)booleanreadBoolean()doublereadDouble()floatreadFloat()bytereadByte()shortreadShort()intreadInt()longreadLong()StringreadUTF()16過濾器輸入流FilterInputStream的子類⑴數據過濾器輸入流FilterInputStream的子類⑵數據輸出流DataOutputStream定義:publicclassDataOutputStreamextendsFilterOutputStreamimplementsDataOutput構造函數:publicDataOutputStream(OutputStreamout)方法如下:publicfinalintsize()以下方法修飾為public,返回值為void:flush(),清空此數據輸出流。write(intb)write(byte[]b,intoff,intlen)writeBoolean(Booleanv)writeByte(intv)writeBytes(Strings)writeChar(intv)publicfinalvoidwriteUTF(Stringstr)writeDouble(doublev)writeFloat(floatv)writeInt(intv)writeLong(longv)writeShort(intv)17過濾器輸入流FilterInputStream的子類⑵數據⑶緩沖輸入流BufferedInputStream定義:publicclassBufferedInputStreamextendsFilterInputStream構造函數:publicBufferedInputStream(InputStreamin)publicBufferedInputStream(InputStreamin,intsize)創建一個帶有基本輸入流in為參數的緩沖輸入流。此緩沖區是內部緩沖區數組buf。size為設定的緩沖區大小。方法如下:read(),從輸入流中讀取一個數據字節。返回一個0到255范圍內的int字節值。read(byte[]b,intoff,intlen),從此字節輸入流中給定起始位置off,開始讀取長度len個字節數到指定的byte數組中。b為目標緩沖區。off為開始存儲字節處的偏移量。len要讀取的最大字節數。18⑶緩沖輸入流BufferedInputStream定義:1⑷緩沖輸出流BufferedOutputStream定義:publicclassBufferedOutputStreamextendsFilterOutputStream構造函數:publicBufferedOutputStream(OutputStreamout)publicBufferedOutputStream(OutputStreamout,intsize)創建一個緩沖輸出流,以將數據寫入指定的底層輸出流。Out為底層輸出流;size為設定的緩沖區大小。方法如下:write(intb),將指定的字節寫入此緩沖的輸出流。write(byte[]b,intoff,intlen),將指定byte數組中從位置off開始的長度len個字節寫入此緩沖的輸出流。b為數據;off為數據的起始偏移量;len為要寫入的字節數。flush(),刷新此緩沖的輸出流。這迫使所有緩沖的輸出字節被寫出到底層輸出流中。19⑷緩沖輸出流BufferedOutputStream定義:2.讀取器和寫入器在網絡通信中,是以字節為單位,就必須將字符流轉換成字節流,才能實現讀取器和寫入器的網絡通信。重點討論與實現網絡編程有關的讀寫器子類和轉換器。讀取器Reader的子類(流),BufferedReader和InputStreamReader,寫入器Writer的子類BufferedWriter、OutputStreamWriter和PrintWriter都與網絡編程有關。202.讀取器和寫入器在網絡通信中,是以字節為單位,就必須將字符2.讀取器和寫入器⑴緩沖字符讀取器BufferedReader定義:publicclassBufferedReaderextendsReader構造函數:publicBufferedReader(Readerin)publicBufferedReader(Readerin,intsz)方法如下:readLine(),讀取一個文本行;read(),讀取單個字符。⑵字節流與字符流輸入轉換器InputStreamReader定義:publicclassInputStreamReaderextendsReader構造函數:publicInputStreamReader(InputStreamin)publicInputStreamReader(InputStreamin,Charsetcs)publicInputStreamReader(InputStreamin,CharsetDecoderdec)publicInputStreamReader(InputStreamin,StringcharsetName)對應的方法在此不討論,可參考相關資料。212.讀取器和寫入器⑴緩沖字符讀取器BufferedRead2.讀取器和寫入器⑶緩沖字符寫入器BufferedWriter定義:publicclassBufferedWriterextendsWriter構造函數:publicBufferedWriter(Writerout)publicBufferedWriter(Writerout,intsz)方法如下:flush();write(char[]cbuf,intff,intlen);write(intc);write(Strings,intoff,intlen)⑷字符流與字節流輸出轉換器OutputStreamWriter定義:publicclassOutputStreamWriterextendsWriter構造函數:publicOutputStreamWriter(OutputStreamout)對應的方法在此不討論,可參考相關資料。222.讀取器和寫入器⑶緩沖字符寫入器BufferedWrit2.讀取器和寫入器⑸字符格式化文本輸出流PrintWriter字符格式化文本輸出流,它不包含用于寫入原始字節的方法,對于這些字節,程序應該使用未編碼的字節流進行寫入。定義:publicclassPrintWriterextendsWriter構造函數:publicPrintWriter(Writerout,booleanautoFlush),參數:out為字符輸出流。autoFlush為boolean變量,如果為true,則println、printf或format方法將刷新輸出緩沖區。方法如下:print(Strings),輸出字符串s。按照默認字符編碼轉換為字節,以write(int)方法寫入這些字節。println(Stringx),輸出字符串x,然后終止該行。format(Stringformat,Object...args),使用指定格式字符串和參數將一個格式化字符串寫入此writer中。返回PrintWriter對象。如果啟用自動刷新,則調用此方法將刷新輸出緩沖區。232.讀取器和寫入器⑸字符格式化文本輸出流PrintWrit3.網絡通信中
基于套接字輸入流和輸出流的創建要實現套接字的網絡通信,需要分四個步驟來完成:①創建套接字socket(Socket),連接成功后形成網絡連接通道;②完成綁定套接字通信的輸入流和輸出流對象的創建;③用輸入和輸出流對象調用其對應方法的操作方式實現網絡通信;④網絡通信結束,需要關閉輸入流和輸出流對象,尤其要關閉套接字對象。243.網絡通信中
基于套接字輸入流和輸出流的創建要實現套接字的⑴基于套接字的字節輸入流dis和輸出流dos的創建,以及網絡編程實例importjava.io.*;import.*;publicclassDS_Client4_1{ publicstaticvoidmain(String[]args)throwsIOException{
//①建立Socket,服務器在本機的8888端口處進行“偵聽” Socketsocket=newSocket("",8888);//建立套接字 System.out.println("客戶端套接字信息:"+socket); try{//②套接字建立成功后,建立字節輸入流dis和輸出流dos對象 DataInputStreamdis=newDataInputStream(socket.getInputStream()); DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());
//③調用其對應方法進行網絡通信 for(inti=0;i<6;i++){ dos.writeUTF("客戶端測試:"+i); //向服務器發數據 dos.flush(); //刷新輸出緩沖區,以便立即發送 System.out.println(dis.readUTF()); //將從服務器接收的數據輸出 } dos.writeUTF("end"); //向服務器發送終止標志 dos.flush(); //刷新輸出緩沖區,以便立即發送
//④關閉對象 dos.close();//關閉輸出流對象dos dis.close();//關閉輸入流對象dis }finally{ System.out.println("客戶端結束……"); socket.close();//關閉套接字對象socket } }}25⑴基于套接字的字節輸入流dis和輸出流dos的創建,以及網⑵基于套接字的具有緩沖的字節輸入流dinB和輸出流dosB的創建importjava.io.*;import.*;publicclassBP_Client4_2{publicstaticvoidmain(String[]args)throwsIOException{ //①建立Socket,服務器在本機的8888端口處進行“偵聽” Socketsocket=newSocket("",8888);//建立套接字 try{
//②套接字建立成功后,通過轉換器建立字符輸入流br和自動刷新輸出流pw BufferedReaderbr=newBufferedReader( newInputStreamReader( socket.getInputStream())); PrintWriterpw=newPrintWriter( newBufferedWriter(newOutputStreamWriter( socket.getOutputStream())),true);轉換器轉換器26⑵基于套接字的具有緩沖的字節輸入流dinB和輸出流dosB
//③調用其對應方法進行網絡通信 for(inti=0;i<10;i++){ //向服務器發數據,并自動刷新輸出緩沖區pw.println("測試:"+i); Stringstr=br.readLine();//從服務器接收數據 System.out.println(str);//將從服務器接收的數據輸出 } //向服務器發送終止標志,并自動刷新輸出緩沖區pw.println("end");
//④關閉對象 pw.close();//關閉輸出流對象pw br.close();//關閉輸入流對象br }finally{ System.out.println("結束……"); socket.close();//關閉套接字對象socket }}}27 //③調用其對應方法進行網絡通信274.1.4對象持久性和對象序列化對象序列化:將對象轉換為可保持或傳輸的格式的過程。就是將整個對象寫入字節流中,這樣形成字節流序列才能在網絡上傳輸,也可以將對象保存在文件中。反序列化:它將流轉換為對象。對象的反序列化,把接收到的字節流序列或文件完全恢復成原來的對象。對象持久性:指保持對象,甚至在多次執行同一程序之間也能保持對象。對象的網絡傳輸或保存到文件中就是對象持久化,它不隨本地主機的程序終止而消失或被破壞。對象持久性和序列化可以實現分布式對象。在Java中,java.io包中的ObjectInputStream類和ObjectOutputStream類,分別為對象輸入流和對象輸出流,以及Serializable接口構成實現對象序列化基本類和接口。
284.1.4對象持久性和對象序列化對象序列化:28ObjectInputStream和ObjectOutputStrea類定義:publicclassObjectInputStreamextendsInputStreamimplementsObjectInput,ObjectStreamConstantspublicclassObjectOutputStreamextendsOutputStreamimplementsObjectOutput,ObjectStreamConstants構造函數:publicObjectInputStream(InputStreamin)throwsIOException,創建從指定in讀取對象流。publicObjectOutputStream(OutputStreamout)throwsIOException,創建指定out的寫入對象流。常用方法publicfinalObjectreadObject()throwsIOException,ClassNotFoundException,從對象輸入流讀取對象。publicfinalvoidwriteObject(Objectobj)throwsIOException,將指定的對象寫入對象輸出流。異常:ClassNotFoundException找不到序列化對象的類。IOException任何常規的輸入/輸出相關的異常。29ObjectInputStream和ObjectOutput對象持久性和對象序列化的網絡編程實例通過服務器(例程4-3)對象序列化在網絡上傳輸,發送至客戶端;客戶端(例程4-4)接收后反序列化恢復為原多行文本框控件,并顯示。先運行服務器程序,即例程4-3,再運行客戶端程序,即例程4-4例程4-3對象序列化服務器程序,OS_Server4_3.java例程4-4對象反序列化客戶端程序,OS_Client4_4.java程序對象序列化和反序列化是一個封裝多行文本框控件的類boy。30對象持久性和對象序列化的網絡編程實例通過服務器(例程4-34.2基于TCP協議的套接字通信在Internet上使用得最普遍的通信方式是基于TCP協議的套接字(Socket)的通信,它把用戶代碼與TCP/IP協議的底層實現隔離開了。用戶可快速地開發出自定制的客戶端和服務器應用程序。4.2.1TCP套接字4.2.2Socket類4.2.3ServerSocket類4.2.4異常處理4.2.5TCP網絡通信實例314.2基于TCP協議的套接字通信在Internet上使用得4.2.1TCP套接字一個套接字Socket就是在網絡上運行的兩個程序間的雙向通信通道的一個端點,兩個程序通過各自的套接字實現程序間的與網絡拓撲結構無關的通信。客戶端程序和服務器必須使用同樣的通信協議,這就是TCP協議,即它們在傳送的信息所使用的語言上達成一致。在Java的包中提供了兩個套接字類,如客戶端程序的套接字Socket和服務器端的套接字SererSocket,它們很好地支持了TCP套接字。另外包還提供了表示互聯網IP地址的InetAddress類,用來設置或獲取IP地址和主機域名(DNS)。見例程4-5InetAddress類的使用程序InetAddressTest4_5.java套接字通信是利用IP地址和端口Port進行的,是一種基礎性的底層連接。一般步驟是:首先,服務器“偵聽”其端口進入的連接。其次,客戶端套接字cS與服務器的端口連接建立套接字sS級別的連接通道。再次,客戶端與服務器分別通過綁定sS和cS套接字連接通道的輸入輸出流操作,實現網絡通信與服務。324.2.1TCP套接字一個套接字Socket就是在網絡上4.2.2Socket類Socket類為客戶端的通信套接字。以下三個功能:由構造函數,定義指定遠端IP地址、端口進行連接通信的通信套接字socket。將此socket以字節輸入流和輸出流的形式返回,當與數據輸入流和輸出流綁定,便可實現客戶端的網絡通信。也可通過方法獲得已連接的socket的遠端IP地址、端口。1.Socket定義和構造函數2.返回輸入流和輸出流的方法3.獲取Socket信息方法334.2.2Socket類Socket類為客戶端的通信套接1.Socket定義和構造函數Socket構造函數均為public修飾類型,如果創建socket時發生I/O錯誤,均拋出IOException異常。定義和常用的構造函數如下:定義:publicclassSocketextendsObject構造函數:Socket(InetAddressaddress,intport)創建一個socket并與指定的IP地址的指定的端口相連接。address為指定的IP地址。port為指定的端口。Socket(Stringhost,intport)創建一個socket并與指定的主機的指定的端口相連接。host為指定的主機的字符串名。port為指定的端口。如果無法確定主機的IP地址還拋出UnknownHostException異常。341.Socket定義和構造函數Socket構造函數均為pub2.返回輸入流和輸出流的方法publicInputStreamgetInputStream()throwsIOException返回此套接字的輸入流。publicOutputStreamgetOutputStream()throwsIOException返回此套接字的輸出流。套接字建立成功后,建立字節輸入流dis和輸出流dos對象:DataInputStreamdis=newDataInputStream(socket.getInputStream());DataOutputStreamdos=newDataOutputStream(socket.getOutputStream());352.返回輸入流和輸出流的方法publicInputStre3.獲取Socket信息方法此類方法可獲取socket所連接的遠端IP地址、端口號,及所綁定的本地IP地址、端口號。另外,socket用完需要用方法關閉。方法如下:publicInetAddressgetInetAddress()獲取socket所連接的遠端IP地址。publicInetAddressgetLocalAddress()獲取socket所綁定的本地IP地址。publicintgetPort()獲取socket所連接的遠端端口號。publicintgetLocalPort()獲取socket所綁定到的本地端口號。publicvoidclose()throwsIOException關閉socket。StringtoString()將此socket轉換為String。363.獲取Socket信息方法此類方法可獲取socket所連接4.2.3ServerSocket類ServerSocket類為服務器的通信套接字。用來偵聽客戶端請求的連接,并為每個新連接創建一個socket對象,由此創建綁定此socket的輸入流和輸出流,與客戶端實現網絡通信。1.定義與構造函數2.常用成員方法374.2.3ServerSocket類ServerSock1.定義與構造函數定義:publicclassServerSocketextendsObject構造函數:ServerSocket(intport)在所給定的用來偵聽的端口上建立一個服務器套接字。如果端口號為零,則在任意的空閑的端口上創建一個服務器套接字。外來連接請求的數量默認最大為50。port參數為在服務器上所指定的用來偵聽的端口。ServerSocket(intport,intbacklog)在所給定的用來偵聽的端口上建立一個服務器套接字。如果端口號為零,則在任意的空閑的端口上創建一個服務器套接字。外來連接請求的最大連接數量由backlog指定。381.定義與構造函數定義:382.常用成員方法此類方法關鍵是偵聽連接端口,建立與客戶端的套接字連接。服務器套接字用完需要用方法關閉。方法如下:publicSocketaccept()throwsIOException偵聽并接收指向本套接字的連接,返回客戶端連接套接字。本方法將造成阻塞直到連接成功。如果在等待連接時套接字發生I/O錯誤,則拋出異常IOException。publicvoidclose()throwsIOException關閉本ServerSocket。如果在關閉本ServerSocket時發生I/O錯誤,則拋出異常IOException。publicInetAddressgetInetAddress()獲取此服務器端套接字的本地IP地址。publicintgetLocalPort()獲取此套接字偵聽的端口。StringtoString()作為String返回此套接字的實現IP地址和實現端口。392.常用成員方法此類方法關鍵是偵聽連接端口,建立與客戶端的套建立數據輸入流dis過程服務器端程序。建立數據輸入流dis和輸出流過程類似。以創建和使用輸入流dis為例。ServerSockets=newServerSocket(PORT);DataInputStreamdis=:偵聽PORT端口,獲得客戶端套接字Socketss=s.accept();newDataInputStream(ss.getInputStream());while(true){//從客戶端中讀數據Stringstr=dis.readUTF();}創建捆綁客戶端套接字的數據輸入流建立服務器ServerSocket套接字通過數據輸入流操作讀取數據40建立數據輸入流dis過程服務器端程序。建立數據輸入流dis和例程4-6服務器端程序DS_Server4_6.javaimportjava.io.*;import.*;publicclassDS_Server4_6{ publicstaticfinalintPORT=8888; publicstaticvoidmain(String[]args)throwsIOException{ ServerSockets=newServerSocket(PORT);//建立服務器ServerSocket套接字 System.out.println("服務器套接字信息:"+s); try{//程序阻塞,等待連接。即直到有一個客戶請求到達,程序方能繼續執行 Socketss=s.accept();//偵聽PORT端口,獲得客戶端套接字 System.out.println("套接字接收到的信息:"+ss); try{//連接成功,建立相應的數據輸入輸出流 DataInputStreamdis=newDataInputStream(ss.getInputStream()); DataOutputStreamdos=newDataOutputStream(ss.getOutputStream()); //在死循環中,來與客戶端通信 while(true){// Stringstr=dis.readUTF(); //從客戶端中讀數據 if(str.equals("end"))break;//當讀到end時,程序終止 System.out.println(str); dos.writeUTF("服務器應答:"+str);//向客戶端中寫數據 } dos.close();//關閉輸出流對象dos dis.close();//關閉輸入流對象dis }finally{ ss.close();//關閉套接字 } }finally{ System.out.println("服務器結束……"); s.close();//關閉服務器套接字 } }}41例程4-6服務器端程序DS_Server4_6.javaim4.2.4異常處理IOException異常Socket類發生I/O錯誤,出現異常,是在創建套接字時、在連接期間發生錯誤時、關閉套接字時、綁定操作失敗或者已經綁定了套接字時、在創建輸入流時或沒有關閉套接字或沒有連接套接字或關閉了套接字輸入、創建輸出流時或者沒有連接套接字時,系統均會拋出IOException異常。ServerSocket類也發生I/O錯誤,出現異常,是在打開套接字時、關閉套接字時、綁定操作失敗或者已經綁定了套接字、等待連接時,系統則會拋出IOException異常。這類通用的異常,采用try/catch/finally結構來拋出、捕捉和處理就可以了。424.2.4異常處理IOException異常424.2.5TCP網絡通信實例在上例(例程4-1和例程4-6)中,為單線程通信。用多線程機制實現服務器能同時處理多個客戶端的請求與聊天。常用的方法是在服務器程序中,accept()返回一個socket后,就用它新建一個線程,令一個線程只為它特定的客戶服務。然后再調用accept(),等待下一次新的連接請求,同時產生下一個新的客戶線程。例程4-7和例程4-8是一個多線程服務器和客戶端網絡程序,可服務多個客戶的。可以看到它與上例很相似,只是將為一個特定的客戶提供服務的所有操作都已移入一個獨立的線程類中。434.2.5TCP網絡通信實例在上例(例程4-1和例程4-例程4-7:多線程服務器端程序MBP_Server4_7.javaimport.*;importjava.io.*;publicclassMBP_Server4_7{publicstaticfinalintPORT=8888;publicstaticvoidmain(String[]args)throwsIOException{ServerSocketss=newServerSocket(PORT);//創建服務器套接字System.out.println("服務器開啟!");try{while(true){Sockets=ss.accept();//偵聽服務器定端口PORT,接收客戶端套接字try{newServerOne(s);//啟動一個新的線程,并把accept()得到的socket傳入新線程中}catch(IOExceptione){s.close();//關閉套接字}}}finally{ss.close();//關閉服務器套接字}}}//用于為特定用戶服務的線程類classServerOneextendsThread{privateSockets;privateBufferedReaderin;privatePrintWriterout;publicServerOne(Sockets)throwsIOException{this.s=s;//創建緩沖字符讀入器in和字符文本輸出流outin=newBufferedReader(newInputStreamReader(s.getInputStream()));out=newPrintWriter(newBufferedWriter(newOutputStreamWriter(s.getOutputStream())),true);start(); //啟動}publicvoidrun(){ //線程自動運行try{while(true){Stringstr=in.readLine();//接收客戶端信息if(str.equals("end"))break;System.out.println("服務器:接收客戶端信息:"+str);out.println("Echo:"+str);//向客戶端發送信息}System.out.println("closing…");}catch(IOExceptione){}finally{try{s.close();//關閉套接字}catch(IOExceptione){}}}}44例程4-7:多線程服務器端程序MBP_Server4_7.j例程4-8:多線程客戶端程序MBP_Client4_8.javaimport.*;importjava.io.*;publicclassMBP_Client4_8extendsThread{//允許創建的線程的最大數staticfinalintMAX_THREADS=25;privatestaticintid=0;//每一個線程的id都不同privatestaticintthreadCount=0;//當前活動的線程數privateSockets;privateBufferedReaderin;privatePrintWriterout;publicstaticintgetThreadCount(){returnthreadCount;}publicMBP_Client4_8(InetAddressia){threadCount++;id++;System.out.println("Makingclient:"+id);try{s=newSocket(ia,MBP_Server4_7.PORT);//創建套接字}catch(IOExceptione){}try{//創建緩沖字符讀入器in和字符文本輸出流outin=newBufferedReader(newInputStreamReader(s.getInputStream()));out=newPrintWriter(newBufferedWriter(newOutputStreamWriter(s.getOutputStream())),true);start(); //啟動}catch(IOExceptione1){try{s.close();//關閉套接字}catch(IOExceptione2){}}}publicvoidrun(){//線程自動運行try{Stringstr;for(inti=0;i<5;i++){out.println("Client#"+id+":"+i);//發送信息str=in.readLine();//接收服務器信息System.out.println("客戶端:發送信息#"+id+":"+i+",服務器應答信息:"+str); }out.println("end");//告知服務器本線程結束}catch(IOExceptione){}finally{try{s.close();}catch(IOExceptione){}}}publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{InetAddressia=InetAddress.getByName(null); //參數null代表本地主機while(true){if(getThreadCount()<MAX_THREADS)newMBP_Client4_8(ia);//新建客戶端線程elsebreak;//當前線程數大于MAX_THREADS,退出結束
//當前運行的線程休眠(暫停執行)10msThread.currentThread().sleep(10);}}}45例程4-8:多線程客戶端程序MBP_Client4_8.ja4.3基于UDP協議的
數據報和套接字用戶數據報協議UDP與TCP協議相反,它并不刻意追求數據報會完全發送出去,也不能擔保它們抵達的順序與它們發出時是一樣的,是一種不可靠數據傳輸協議。比TCP協議具有開銷少、傳輸速度快。
4.3.1UDP概述4.3.2DatagramPacket類4.3.3DatagramSocket類4.3.4構建UDP客戶端/服務器4.3.5UDP網絡應用實例464.3基于UDP協議的
數據報和套接字用戶數據報協議UDP4.3.1UDP概述Java中實現UDP協議的兩個類DatagramPacket數據包類:將數據打成UDP數據包,也可將接收的UDP數據包解包成數據;DatagramSocket數據報套接字類:用于發送和接收UDP數據報。不分客戶端和服務器套接字。用戶接收數據時,從DatagramSocket接收DatagramPacket對象,并讀取數據包的內容。474.3.1UDP概述Java中實現UDP協議的兩個類474.3.2DatagramPacket類數據包DatagramPacket類所定義的對象表示為一個數據包,依據設定可確定數據包的大小。每個數據包中應該包含:源和目標地址、源和目標端口這些信息。才能在網絡上通過路由器選定的路徑傳輸,從始發源主機傳送到目的主機。484.3.2DatagramPacket類數據包Datag1.DatagramPacket的定義和構造函數定義:publicfinalclassDatagramPacketextendsObject構造函數:publicDatagramPacket(byte[]buf,intlength):buf表示接收數據的緩沖區;length表示接收數據的最大長度,它必須小于等于buf.length,通常為buf的長度。publicDatagramPacket(byte[]buf,intoffset,intlength):offset為在緩沖區中指定了偏移量。publicDatagramPacket(byte[]buf,intlength,InetAddressaddress,intport):創建數據報包。buf中存放發送的數據;length表示發送數據的長度;address表示目的地址;port表示目的端口號。DatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport):offset為在緩沖區中指定了偏移量。491.DatagramPacket的定義和構造函數定義:pub2.常用方法publicInetAddressgetAddress():發送數據包時,返回接收數據包的主機的IP地址;接收數據包時,返回發出數據包的主機IP地址。publicintgetPort():發送數據包時,返回接收數據包的主機端口號;接收數據包時,返回發出數據包的主機端口號。publicintgetLength():返回被接收或發送的數據的長度。publicbyte[]getData():返回被接收或發送的緩沖區數據。publicintgetOffset():返回被接收或發送的數據的偏移量。publicvoidsetAddress(InetAddressiaddr):發送數據包時,設置返回接收數據包的主機IP地址;接收數據包時,設置返回發出數據包的主機IP地址。publicvoidsetPort(intiport):遠程主機上的端口號。publicvoidsetLength(intlength):為此包設置長度。publicvoidsetData(byte[]buf):數據緩沖區。502.常用方法publicInetAddressgetAd4.3.3DatagramSocket類在客戶端和服務器都需要建立一個DatagramSocket對象,然后通過receive()方法接收數據包,通過send()方法發送數據包。無須像TCP協議套接字一樣,還要建立會話流來傳送數據。1.DatagramSocket的定義和構造函數2.常用方法514.3.3DatagramSocket類在客戶端和服務器1.DatagramSocket的定義和構造函數定義:publicclassDatagramSocketextendsObject構造函數:publicDatagramSocket()throwsSocketException:創建數據報套接字,系統自動將它與本地主機上的某個可使用的端口綁定在一起。publicDatagramSocket(intport)throwsSocketException:創建數據報套接字,并將它與本地主機的一個指定的端口(port)綁定在一起。publicDatagramSocket(intport,InetAddressladdr)throwsSocketException:創建數據報套接字,將其綁定到指定的本地laddr地址和端口port。拋出異常SocketException:如果數據報套接字不能被創建或不能與本地端口聯系起來,就拋出異常。521.DatagramSocket的定義和構造函數定義:pub2.常用方法publicvoidreceive(DatagramPacketp)throwsIOException:從數據報套接字接收一個數據包。本方法返回時,數據包p中存放被接收的數據,且數據包中也含有發送地的IP地址和端口號。如果發生IO錯誤,就拋出異常IOException。publicvoidsend(DatagramPacketp)throwsIOException:發送數據包DatagramPacket將包括數據內容、數據長度、目的IP地址和端口的信息。拋出異常IOException。publicvoidclose():關閉套接字。publicInetAddressgetLocalAddress():獲取套接字綁定的本地地址。publicintgetLocalPort():獲取此套接字綁定的本地主機上的端口號532.常用方法publicvoidreceive(Data4.3.4構建UDP客戶端/服務器服務器:建立數據包DatagramPacket的對象,未知客戶端的IP和Port,但需要設置數據緩沖區的大小。建立數據報套接字DatagramSocket的對象時,需要確定和綁定服務器端口Port,以便由此端口接收客戶端數據包。服務器先接收客戶端發來的數據包,然后發送數據包。客戶端:建立數據包DatagramPacket的對象時,必須已知目的(服務器)InetAddress地址和端口Port,并設置,以便數據包發送至目的地,確定數據包緩沖區大小。建立數據報套接字DatagramSocket的對象時,可不設定端口,系統自動獲取客戶端端口Port。客戶端先發送數據包,后接收數據包。544.3.4構建UDP客戶端/服務器服務器:54例程4-9:UDP協議服務器程序UDPServer4_9.javaimport.*;publicclassUDPServer4_9extendsObject{publicstaticfinalintPORT=8765; //服務器端口publicstaticvoidmain(Stringargs[]){try{);//建立指定端口Port的數據報套接字對象DatagramSocketdgs=newDatagramSocket(PORTbyte[]buf=newbyte[1024];//建立數據包對象,未知客戶端的IP和Port,自動帶自己(服務器端)的IP和PortDatagramPacketp=newDatagramPacket(buf,buf.length);System.out.println("服務器啟動!");for(inti=0;i<3;i++){dgs.receive(p); //服務器收到數據包,帶有客戶端的IP和PortSystem.out.println("服務器收到數據報:#"+i+";"+newString(p.getData(),0,p.getLength()));dgs.send(p); //向客戶端發送帶有客戶端的IP和Port的數據包p}}catch(Exceptione){e.printStackTrace();}}}55例程4-9:UDP協議服務器程序UDPServer4_9.j例程4-10:UDP協議客戶端程序UDPClient4_10.javaimport.*;publicclassUDPClient4_10extendsObject{publicstaticInetAddressia;publicstaticfinalintPORT=8765; //服務器端口publicstaticStringstr="你好!"; //發送內容publicstaticvoidmain(Stringargs[]){try{//服務器主機IP地址ia=InetAddress.getLocalHost(); DatagramSocketdgs=newDatagramSocket();//數據報套接字對象,自動分配端口號byte[]buf=newbyte[1024];buf=str.trim().getBytes(); //發送內容//建立數據包對象(設置有服務器的IP和Port,自動加載自己(客戶端)的IP和Port)DatagramPacketp=newDatagramPacket(buf,buf.length,ia,PORT);for(inti=0;i<3;i++){dgs.send(p);//客戶端向服務器發送帶有服務器端的IP和Port的數據包pSystem.out.println("客戶端發送完畢數據報!");dgs.receive(p); //客戶端接收數據包System.out.println("客戶端接收到返回的數據報:#"+i+";"+newString(p.getData(),0,p.getLength()));Thread.sleep(900);}}catch(Exceptione){e.printStackTrace();}}}56例程4-10:UDP協議客戶端程序UDPClient4_104.3.5UDP網絡應用實例例程4-11是一個多線程點對點的UDP協議網絡應用實例。該程序由三部分組成:登錄設置對話框(setDialog)、數據發送與接收窗口(DSR_Frame)和客戶線程(LoginClient)。本程序主要實現如下功能:①設置用戶名、用戶主機端口和對話客戶的IP地址和端口。②每個用戶可同時發送和接收信息。③兩個用戶間對話和通過改變IP地址和端口設置與其他用戶對話。程序啟動后,打開“登錄設置”對話框,先設置用戶名、對方主機名IP、對方端口和自己接收端口,單擊“確定”按鈕,進入“數據發送與接收”窗口。對方主機名IP和發送對方端口必須事先知道,并正確設置,雙方才能正常發送和接收數據。例如,用戶名:“北京”,對方主機名IP:“”,發送對方端口:“777”,自己接收端口:“666”;另一用戶名:“上海”,則發送對方端口只能是“666”,自己接收端口也只能是“777”。先啟動程序按用戶名“北京”設置,再啟動程序按用戶名“上海”設置,這樣兩人就可以相互發送與接收數據。也可以打開第三個用戶,第三個用戶能和誰進行數據發送和接收,取決于發送對方的端口設置。574.3.5UDP網絡應用實例例程4-11是一個多線程點對4.4組播套接字組播傳遞(MulticastDelivery)技術越來越多地應用于網絡數據傳輸,它更適合于網絡多媒體業務。在Java中,為實現IP組播(1P多點傳送)包中提供了MulticastSocket類稱組播套接字和在組內發送和接收DatagramPacket數據包。4.4.1組播傳播方式4.4.2組播Socket類4.4.3組播Socket的實例584.4組播套接字組播傳遞(MulticastDelive4.4.1組播傳播方式網絡數據傳輸按照接收者的數量,可分為三種方式:單播(Unicast)傳輸:在發送者和每一個接收者之間實現點到點網絡連接。廣播(Broadcast)傳輸:指在IP子網內廣播數據包,所有在子網內部的主機都將收到這些數據包中。電視臺就是采用廣播方式。組播(Multicast)傳輸:發送者每次發送的數據可以被組內的所有接收者收到。在組內的發送者和每一個接收者之間實現點到多點網絡傳輸,也稱多點傳送。組播是介于單播傳輸和廣播傳輸之間的一種中間技術。它可大大提高數據傳送效率,減少了骨干網絡出現擁塞的可能性。比前兩種方式的效率都很高。594.4.1組播傳播方式網絡數據傳輸按照接收者的數量,可分圖4-2組播與非組播數據包傳輸和復制過程組播傳輸,僅在通過的路由器2和路由器4上的數據被復制傳輸,在其余結點上無須復制數據。在主機1通過路由器1到路由器2的傳輸路徑上,數據只需傳送一次。而非組播傳輸,路由器1發送4個獨立的相同數據流到路由器2,再到每臺主機上。60圖4-2組播與非組播數據包傳輸和復制過程組播傳輸,僅在組播地址組播組內的所有主機共享同一個地址。組播地址使用的是D類IP地址,它的最高二進制四位為“1110”,十進制范圍為~55。永久組播地址:大多數以224.0、224.1、224.2或239開頭的地址。臨時組的組播地址:可以在創建新的組播時由用戶選取,~55。本地管理組播地址:~55。組播組是開放的,主機可以在任何時候進入或離開組。61組播地址組播組內的所有主機共享同一個地址。61數據包的生存期TTL(TimeToLive)組播分組在網絡上的轉發是由支持組播的路由器來處理的,組播數據包將發送給網絡上組內的所有成員,組播數據包傳遞的范圍由數據包的生存期TTL(TimeToLive)值決定。TTL通過限制IP數據包丟失前通過的路由器數目來決定IP數據包的生存時間,取值范圍為0~255。TTL值指定了IP數據包應該傳播的范圍,IP數據包能夠跨過多少個網絡,當數據包通過路由器被轉發一次,數據包中的TTL值將減1。TTL為0,這個包就被丟棄,不再向前轉發;TTL為1時,指定數據包只能發送到本地子網絡;TTL為255時,指定數據包能發送到世界范圍的所有網站。62數據包的生存期TTL(TimeToLive)組播分組在4.4.2組播Socket類組播Socket類是指組播套接字MulticastSocket類,它是基于數據報套接字DatagramSocket類繼承而來的,因此,它也是無連接通信,可使用DatagramSocket類的方法。數據包DatagramPacket類用來存放發送和接收的組播數據包。增加了組播的一些特定功能。634.4.2組播Socket類組播Socket類是指組播套1.MulticastSocke的定義和構造函數定義:publicclassMulticastSocketextendsDatagramSocket構造函數:publicMulticastSocket()throwsIOException:創建組播套接字。publicMulticastSocket(intport)throwsIOException:創建組播套接字并將其綁定到指定端口port。641.MulticastSocke的定義和構造函數定義:pub2.常用方法組播套接字特有的方法:publicInetAddressgetInterface()throwsSocketException:獲取用于組播數據包的網絡接口的地址。publicvoidsetInterface(InetAddressinf)throwsSocketException:設置組播網絡接口,供其行為將受網絡接口值影響的方法使用。對多宿主機(multihomedhost)很有用。publicintgetTimeToLive()throwsIOException:獲取在套接字上發出的組播數據包的默認生存時間。publicvoidsetTimeToLive(intttl)throwsIOException:設置在此MulticastSocket上發出的組播數據包的默認生存時間,以便控制組播的范圍。publicvoidjoinGroup(InetAddressmcastaddr)throwsIOException:加入組播組。publicvoidleaveGroup(InetAddressmcastaddr)throwsIOException:離開組播組。652.常用方法組播套接字特有的方法:65以下3個方法從父類DatagramSocket繼承過來的:publicvoidsend(DatagramPacketp)throwsIOException:向組內成員發送數據包,DatagramPacket將包括數據內容、數據長度、目的IP地址和端口的信息。同上拋出異常IOException。TTL值缺省時為1。publicvoidreceive(DatagramPacketp)throwsIOException:從組播套接字接收一個數據包。本方法返回時,數據包p中存放被接收的數據,且數據包中也含有發送地的IP地址和端口號。如果發生IO錯誤,就拋出異常IOException。publicvoidclose():關閉此組播套接字。還有其
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工業園區規劃設計思路
- 工業排污處理的智能化改造與物聯網
- 工業安全與防護在智能車間的實施要點
- 工業污染源的環境監測與治理策略
- 工業機器人與節能生產技術探討
- 工業機器人技術的進步與應用領域
- 工業綠色制造技術
- 工業物聯網的構建與優化
- 工業級智能穿戴設備的應用與發展趨勢
- 工業節能減排技術解決方案
- 探析3-6年級小學生校園排斥:現狀、歸因與防范路徑
- 人教版(2024)七年級地理下學期期末達標測試卷A卷(含解析)
- 《插花藝術》教材任務-項目三 任務二切花裝飾設計
- 公共組織績效評估-形考任務三(占10%)-國開(ZJ)-參考資料
- 醫學影像讀片試題及答案
- 2025年廣東高中學業水平合格性考試化學試卷試題(含答案解析)
- 2025年突發流行性傳染性疾病應急演練方案及總結
- 安能快遞加盟合同協議
- 2024年大學生就業力調研報告-智聯招聘-202405
- 防靜電地膠板施工工藝及技術方案、措施
- 成人ICU患者外周動脈導管管理專家共識解讀
評論
0/150
提交評論