![基于Socket.doc_第1頁](http://file.renrendoc.com/FileRoot1/2020-1/10/cab629ee-7385-4da2-aa1c-24359ab487a2/cab629ee-7385-4da2-aa1c-24359ab487a21.gif)
![基于Socket.doc_第2頁](http://file.renrendoc.com/FileRoot1/2020-1/10/cab629ee-7385-4da2-aa1c-24359ab487a2/cab629ee-7385-4da2-aa1c-24359ab487a22.gif)
![基于Socket.doc_第3頁](http://file.renrendoc.com/FileRoot1/2020-1/10/cab629ee-7385-4da2-aa1c-24359ab487a2/cab629ee-7385-4da2-aa1c-24359ab487a23.gif)
![基于Socket.doc_第4頁](http://file.renrendoc.com/FileRoot1/2020-1/10/cab629ee-7385-4da2-aa1c-24359ab487a2/cab629ee-7385-4da2-aa1c-24359ab487a24.gif)
![基于Socket.doc_第5頁](http://file.renrendoc.com/FileRoot1/2020-1/10/cab629ee-7385-4da2-aa1c-24359ab487a2/cab629ee-7385-4da2-aa1c-24359ab487a25.gif)
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
基于Socket(套接字)的低層次Java網(wǎng)絡(luò)編程Socket通訊網(wǎng)絡(luò)上的兩個程序通過一個雙向的通訊連接實現(xiàn)數(shù)據(jù)的交換,這個雙向鏈路的一端稱為一個Socket。Socket通常用來實現(xiàn)客戶方和服務(wù)方的連接。Socket是TCP/IP協(xié)議的一個十分流行的編程界面,一個Socket由一個IP地址和一個端口號唯一確定。在傳統(tǒng)的UNIX環(huán)境下可以操作TCP/IP協(xié)議的接口不止Socket一個,Socket所支持的協(xié)議種類也不光TCP/IP一種,因此兩者之間是沒有必然聯(lián)系的。在Java環(huán)境下,Socket編程主要是指基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程。說Socket編程是低層次網(wǎng)絡(luò)編程并不等于它功能不強大,恰恰相反,正因為層次低,Socket編程比基于URL的網(wǎng)絡(luò)編程提供了更強大的功能和更靈活的控制,但是卻要更復(fù)雜一些。由于Java本身的特殊性,Socket編程在Java中可能已經(jīng)是層次最低的網(wǎng)絡(luò)編程接口,在Java中要直接操作協(xié)議中更低的層次,需要使用Java的本地方法調(diào)用(JNI),在這里就不予討論了。前面已經(jīng)提到Socket通常用來實現(xiàn)C/S結(jié)構(gòu)。Socket通訊的一般過程使用Socket進行Client/Server程序設(shè)計的一般連接過程是這樣的:Server端Listen(監(jiān)聽)某個端口是否有連接請求,Client端向Server端發(fā)出Connect(連接)請求,Server端向Client端發(fā)回Accept(接受)消息。一個連接就建立起來了。Server端和Client端都可以通過Send,Write等方法與對方通信。對于一個功能齊全的Socket,都要包含以下基本結(jié)構(gòu),其工作過程包含以下四個基本的步驟:(1) 創(chuàng)建Socket;(2) 打開連接到Socket的輸入/出流;(3) 按照一定的協(xié)議對Socket進行讀/寫操作;(4) 關(guān)閉Socket.第三步是程序員用來調(diào)用Socket和實現(xiàn)程序功能的關(guān)鍵步驟,其他三步在各種程序中基本相同。以上4個步驟是針對TCP傳輸而言的,使用UDP進行傳輸時略有不同創(chuàng)建Socketjava在包中提供了兩個類Socket和ServerSocket,分別用來表示雙向連接的客戶端和服務(wù)端。這是兩個封裝得非常好的類,使用很方便。其構(gòu)造方法如下:Socket(InetAddress address, int port);Socket(InetAddress address, int port, boolean stream);Socket(String host, int prot);Socket(String host, int prot, boolean stream);Socket(SocketImpl impl)Socket(String host, int port, InetAddress localAddr, int localPort)Socket(InetAddress address, int port, InetAddress localAddr, int localPort)ServerSocket(int port);ServerSocket(int port, int backlog);ServerSocket(int port, int backlog, InetAddress bindAddr)其中address、host和port分別是雙向連接中另一方的IP地址、主機名和端口號,stream指明socket是流socket還是數(shù)據(jù)報socket,localPort表示本地主機的端口號,localAddr和bindAddr是本地機器的地址(ServerSocket的主機地址),impl是socket的父類,既可以用來創(chuàng)建serverSocket又可以用來創(chuàng)建Socket。count則表示服務(wù)端所能支持的最大連接數(shù)。例如:Socket client = new Socket(127.0.01., 80);ServerSocket server = new ServerSocket(80);注意,在選擇端口時,必須小心。每一個端口提供一種特定的服務(wù),只有給出正確的端口,才能獲得相應(yīng)的服務(wù)。01023的端口號為系統(tǒng)所保留,例如http服務(wù)的端口號為80,telnet服務(wù)的端口號為21,ftp服務(wù)的端口號為23, 所以我們在選擇端口號時,最好選擇一個大于1023的數(shù)以防止發(fā)生沖突。在創(chuàng)建socket時如果發(fā)生錯誤,將產(chǎn)生IOException,在程序中必須對之作出處理。所以在創(chuàng)建Socket或ServerSocket是必須捕獲或拋出例外。客戶端的Socket下面是一個典型的創(chuàng)建客戶端Socket的過程。trySocket socket=new Socket(,4700); /是TCP/IP協(xié)議中默認(rèn)的本機地址catch(IOException e)System.out.println(Error:+e);這是最簡單的在客戶端創(chuàng)建一個Socket的一個小程序段,也是使用Socket進行網(wǎng)絡(luò)通訊的第一步,程序相當(dāng)簡單,在這里不作過多解釋了。在后面的程序中會用到該小程序段。服務(wù)器端的ServerSocket下面是一個典型的創(chuàng)建Server端ServerSocket的過程。ServerSocket server=null;try server=new ServerSocket(4700); /創(chuàng)建一個ServerSocket在端口4700監(jiān)聽客戶請求catch(IOException e)System.out.println(can not listen to :+e);Socket socket=null;try socket=server.accept(); /accept()是一個阻塞的方法,一旦有客戶請求,它就會返回一個Socket對象用于同客戶進行交互catch(IOException e)System.out.println(Error:+e);以上的程序是Server的典型工作模式,只不過在這里Server只能接收一個請求,接受完后Server就退出了。實際的應(yīng)用中總是讓它不停的循環(huán)接收,一旦有客戶請求,Server總是會創(chuàng)建一個服務(wù)線程來服務(wù)新來的客戶,而自己繼續(xù)監(jiān)聽。程序中accept()是一個阻塞函數(shù),所謂阻塞性方法就是說該方法被調(diào)用后,將等待客戶的請求,直到有一個客戶啟動并請求連接到相同的端口,然后accept()返回一個對應(yīng)于客戶的socket。這時,客戶方和服務(wù)方都建立了用于通信的socket,接下來就是由各個socket分別打開各自的輸入/輸出流。打開輸入/出流類Socket提供了方法getInputStream ()和getOutStream()來得到對應(yīng)的輸入/輸出流以進行讀/寫操作,這兩個方法分別返回InputStream和OutputSteam類對象。為了便于讀/寫數(shù)據(jù),我們可以在返回的輸入/輸出流對象上建立過濾流,如DataInputStream、DataOutputStream或PrintStream類對象,對于文本方式流對象,可以采用InputStreamReader和OutputStreamWriter、PrintWirter等處理。例如:PrintStream os=new PrintStream(new BufferedOutputStreem(socket.getOutputStream();DataInputStream is=new DataInputStream(socket.getInputStream();PrintWriter out=new PrintWriter(socket.getOutStream(),true);BufferedReader in=new ButfferedReader(new InputSteramReader(Socket.getInputStream();輸入輸出流是網(wǎng)絡(luò)編程的實質(zhì)性部分,具體如何構(gòu)造所需要的過濾流,要根據(jù)需要而定,能否運用自如主要看你對Java中輸入輸出部分掌握如何。關(guān)閉Socket每一個Socket存在時,都將占用一定的資源,在Socket對象使用完畢時,要其關(guān)閉。關(guān)閉Socket可以調(diào)用Socket的Close()方法。在關(guān)閉Socket之前,應(yīng)將與Socket相關(guān)的所有的輸入/輸出流全部關(guān)閉,以釋放所有的資源。而且要注意關(guān)閉的順序,與Socket相關(guān)的所有的輸入/輸出該首先關(guān)閉,然后再關(guān)閉Socket。os.close();is.close();socket.close();盡管Java有自動回收機制,網(wǎng)絡(luò)資源最終是會被釋放的。但是為了有效的利用資源,建議你按照合理的順序主動釋放資源。簡單的Client/Server程序設(shè)計下面我們給出一個用Socket實現(xiàn)的客戶和服務(wù)器交互的典型的C/S結(jié)構(gòu)的演示程序,讀者通過仔細(xì)閱讀該程序,會對前面所討論的各個概念有更深刻的認(rèn)識。程序的意義請參考注釋。1. 客戶端程序import java.io.*;import .*;public class TalkClient public static void main(String args) trySocket socket=new Socket(,4700); /向本機的4700端口發(fā)出客戶請求BufferedReader sin=new BufferedReader(new InputStreamReader(System.in);/由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對象PrintWriter os=new PrintWriter(socket.getOutputStream();/由Socket對象得到輸出流,并構(gòu)造PrintWriter對象BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream();/由Socket對象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對象String readline;readline=sin.readLine(); /從系統(tǒng)標(biāo)準(zhǔn)輸入讀入一字符串while(!readline.equals(bye) /若從標(biāo)準(zhǔn)輸入讀入的字符串為 bye則停止循環(huán)os.println(readline); /將從系統(tǒng)標(biāo)準(zhǔn)輸入讀入的字符串輸出到Serveros.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)閉Socketcatch(Exception e) System.out.println(Error+e); /出錯,則打印出錯信息2. 服務(wù)器端程序import java.io.*;import .*;import java.applet.Applet;public class TalkServerpublic static void main(String args) tryServerSocket server=null;try server=new ServerSocket(4700); /創(chuàng)建一個ServerSocket在端口4700監(jiān)聽客戶請求catch(Exception e) System.out.println(can not listen to:+e); /出錯,打印出錯信息Socket socket=null;trysocket=server.accept(); /使用accept()阻塞等待客戶請求,有客戶/請求到來則產(chǎn)生一個Socket對象,并繼續(xù)執(zhí)行catch(Exception e) System.out.println(Error.+e); /出錯,打印出錯信息String line;BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream();/由Socket對象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對象PrintWriter os=newPrintWriter(socket.getOutputStream();/由Socket對象得到輸出流,并構(gòu)造PrintWriter對象BufferedReader sin=new BufferedReader(new InputStreamReader(System.in);/由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對象System.out.println(Client:+is.readLine(); /在標(biāo)準(zhǔn)輸出上打印從客戶端讀入的字符串line=sin.readLine(); /從標(biāo)準(zhǔn)輸入讀入一字符串while(!line.equals(bye) /如果該字符串為 bye,則停止循環(huán)os.println(line); /向客戶端輸出該字符串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)閉Socketserver.close(); /關(guān)閉ServerSocketcatch(Exception e)System.out.println(Error:+e); /出錯,打印出錯信息從上面的兩個程序中我們可以看到,socket四個步驟的使用過程。讀者可以分別將Socket使用的四個步驟的對應(yīng)程序段選擇出來,這樣便于讀者對socket的使用有進一步的了解。你可以在單機上試驗該程序,最好是能在真正的網(wǎng)絡(luò)環(huán)境下試驗該程序,這樣更容易分辨輸出的內(nèi)容和客戶機,服務(wù)器的對應(yīng)關(guān)系。同時也可以修改該程序,提供更為強大的功能,或更加滿足你的意圖。2. 服務(wù)器端程序import java.io.*;import .*;import java.applet.Applet;public class TalkServerpublic static void main(String args) tryServerSocket server=null;try server=new ServerSocket(4700); /創(chuàng)建一個ServerSocket在端口4700監(jiān)聽客戶請求catch(Exception e) System.out.println(can not listen to:+e); /出錯,打印出錯信息Socket socket=null;trysocket=server.accept(); /使用accept()阻塞等待客戶請求,有客戶/請求到來則產(chǎn)生一個Socket對象,并繼續(xù)執(zhí)行catch(Exception e) System.out.println(Error.+e); /出錯,打印出錯信息String line;BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream();/由Socket對象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對象PrintWriter os=newPrintWriter(socket.getOutputStream();/由Socket對象得到輸出流,并構(gòu)造PrintWriter對象BufferedReader sin=new BufferedReader(new InputStreamReader(System.in);/由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對象System.out.println(Client:+is.readLine(); /在標(biāo)準(zhǔn)輸出上打印從客戶端讀入的字符串line=sin.readLine(); /從標(biāo)準(zhǔn)輸入讀入一字符串while(!line.equals(bye) /如果該字符串為 bye,則停止循環(huán)os.println(line); /向客戶端輸出該字符串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)閉Socketserver.close(); /關(guān)閉ServerSocketcatch(Exception e)System.out.println(Error:+e); /出錯,打印出錯信息從上面的兩個程序中我們可以看到,socket四個步驟的使用過程。你可以分別將Socket使用的四個步驟的對應(yīng)程序段選擇出來,這樣便于你對socket的使用有進一步的了解。支持多客戶的client/server程序設(shè)計前面提供的Client/Server程序只能實現(xiàn)Server和一個客戶的對話。在實際應(yīng)用中,往往是在服務(wù)器上運行一個永久的程序,它可以接收來自其他多個客戶端的請求,提供相應(yīng)的服務(wù)。為了實現(xiàn)在服務(wù)器方給多個客戶提供服務(wù)的功能,需要對上面的程序進行改造,利用多線程實現(xiàn)多客戶機制。服務(wù)器總是在指定的端口上監(jiān)聽是否有客戶請求,一旦監(jiān)聽到客戶請求,服務(wù)器就會啟動一個專門的服務(wù)線程來響應(yīng)該客戶的請求,而服務(wù)器本身在啟動完線程之后馬上又進入監(jiān)聽狀態(tài),等待下一個客戶的到來。客戶端的程序和上面程序是完全一樣的,讀者如果仔細(xì)閱讀過上面的程序,可以跳過不讀,把主要精力集中在Server端的程序上。1. 客戶端程序:MultiTalkClient.javaimport java.io.*;import .*;public class MultiTalkClient public static void main(String args) trySocket socket=new Socket(,4700); /向本機的4700端口發(fā)出客戶請求BufferedReader sin=new BufferedReader(new InputStreamReader(System.in);/由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對象PrintWriter os=new PrintWriter(socket.getOutputStream();/由Socket對象得到輸出流,并構(gòu)造PrintWriter對象BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream();/由Socket對象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對象String readline;readline=sin.readLine(); /從系統(tǒng)標(biāo)準(zhǔn)輸入讀入一字符串while(!readline.equals(bye) /若從標(biāo)準(zhǔn)輸入讀入的字符串為 bye則停止循環(huán)os.println(readline); /將從系統(tǒng)標(biāo)準(zhǔn)輸入讀入的字符串輸出到Serveros.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)閉Socketcatch(Exception e) System.out.println(Error+e); /出錯,則打印出錯信息2. 服務(wù)器端程序: MultiTalkServer.javaimport java.io.*;import .*;import ServerThread;public class MultiTalkServerstatic int clientnum=0; /靜態(tài)成員變量,記錄當(dāng)前客戶的個數(shù)public static void main(String args) throws IOException ServerSocket serverSocket=null;boolean listening=true;tryserverSocket=new ServerSocket(4700); /創(chuàng)建一個ServerSocket在端口4700監(jiān)聽客戶請求catch(IOException e) System.out.println(Could not listen on port:4700.); /出錯,打印出錯信息System.exit(-1); /退出while(listening) /永遠循環(huán)監(jiān)聽new ServerThread(serverSocket.accept(),clientnum).start();/監(jiān)聽到客戶請求,根據(jù)得到的Socket對象和客戶計數(shù)創(chuàng)建服務(wù)線程,并啟動之clientnum+; /增加客戶計數(shù)serverSocket.close(); /關(guān)閉ServerSocket3. 程序ServerThread.javaimport java.io.*;import .*;public class ServerThread extends ThreadSocket socket=null; /保存與本線程相關(guān)的Socket對象int clientnum; /保存本進程的客戶計數(shù)public ServerThread(Socket socket,int num) /構(gòu)造函數(shù)this.socket=socket; /初始化socket變量clientnum=num+1; /初始化clientnum變量public void run() /線程主體tryString line;BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream();/由Socket對象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對象PrintWriter os=newPrintWriter(socket.getOutputStream();/由Socket對象得到輸出流,并構(gòu)造PrintWriter對象BufferedReader sin=new BufferedReader(new InputStreamReader(System.in);/由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對象System.out.println(Client:+ clientnum +is.readLine();/在標(biāo)準(zhǔn)輸出上打印從客戶端讀入的字符串line=sin.readLine(); /從標(biāo)準(zhǔn)輸入讀入一字符串while(!line.equals(bye) /如果該字符串為 bye,則停止循環(huán)os.println(line); /向客戶端輸出該字符串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)閉Socketserver.close(); /關(guān)閉ServerSocketcatch(Exception e)System.out.println(Error:+e); /出錯,打印出錯信息這個程序向讀者展示了網(wǎng)絡(luò)應(yīng)用中最為典型的C/S結(jié)構(gòu),我們可以用下面的圖來描述這樣一種模型:通過以上的學(xué)習(xí),你應(yīng)該對Java的面向流的網(wǎng)絡(luò)編程有了一個比較全面的認(rèn)識,這些都是基于TCP的應(yīng)用,后面我們將介紹基于UDP的Socket編程。據(jù)報Datagram通訊前面在介紹TCP/IP協(xié)議的時候,我們已經(jīng)提到,在TCP/IP協(xié)議的傳輸層除了TCP協(xié)議之外還有一個UDP協(xié)議,相比而言UDP的應(yīng)用不如TCP廣泛,幾個標(biāo)準(zhǔn)的應(yīng)用層協(xié)議HTTP,F(xiàn)TP,SMTP使用的都是TCP協(xié)議。但是,隨著計算機網(wǎng)絡(luò)的發(fā)展,UDP協(xié)議正越來越來顯示出其威力,尤其是在需要很強的實時交互性的場合,如網(wǎng)絡(luò)游戲,視頻會議等,UDP更是顯示出極強的威力,下面我們就介紹一下Java環(huán)境下如何實現(xiàn)UDP網(wǎng)絡(luò)傳輸。什么是Datagram所謂數(shù)據(jù)報(Datagram)就跟日常生活中的郵件系統(tǒng)一樣,是不能保證可靠的寄到的,而面向鏈接的TCP就好比電話,雙方能肯定對方接受到了信息。在本章前面,我們已經(jīng)對UDP和TCP進行了比較,在這里再稍作小節(jié):TCP,可靠,傳輸大小無限制,但是需要連接建立時間,差錯控制開銷大。UDP,不可靠,差錯控制開銷較小,傳輸大小限制在64K以下,不需要建立連接??傊?,這兩種協(xié)議各有特點,應(yīng)用的場合也不同,是完全互補的兩個協(xié)議,在TCP/IP協(xié)議中占有同樣重要的地位,要學(xué)好網(wǎng)絡(luò)編程,兩者缺一不可。Datagram通訊的表示方法:DatagramSocket;DatagramPacket包中提供了兩個類DatagramSocket和DatagramPacket用來支持?jǐn)?shù)據(jù)報通信,DatagramSocket用于在程序之間建立傳送數(shù)據(jù)報的通信連接, DatagramPacket則用來表示一個數(shù)據(jù)報。先來看一下DatagramSocket的構(gòu)造方法:DatagramSocket();DatagramSocket(int prot);DatagramSocket(int port, InetAddress laddr)其中,port指明socket所使用的端口號,如果未指明端口號,則把socket連接到本地主機上一個可用的端口。laddr指明一個可用的本地地址。給出端口號時要保證不發(fā)生端口沖突,否則會生成SocketException類例外。注意:上述的兩個構(gòu)造方法都聲明拋棄非運行時例外SocketException,程序中必須進行處理,或者捕獲、或者聲明拋棄。用數(shù)據(jù)報方式編寫client/server程序時,無論在客戶方還是服務(wù)方,首先都要建立一個DatagramSocket對象,用來接收或發(fā)送數(shù)據(jù)報,然后使用DatagramPacket類對象作為傳輸數(shù)據(jù)的載體。下面看一下DatagramPacket的構(gòu)造方法 :DatagramPacket(byte buf,int length);DatagramPacket(byte buf, int length, InetAddress addr, int port);DatagramPacket(byte buf, int offset, int length);DatagramPacket(byte buf, int offset, int length, InetAddress address, int port);其中,buf中存放數(shù)據(jù)報數(shù)據(jù),length為數(shù)據(jù)報中數(shù)據(jù)的長度,addr和port旨明目的地址,offset指明了數(shù)據(jù)報的位移量。在接收數(shù)據(jù)前,應(yīng)該采用上面的第一種方法生成一個DatagramPacket對象,給出接收數(shù)據(jù)的緩沖區(qū)及其長度。然后調(diào)用DatagramSocket 的方法receive()等待數(shù)據(jù)報的到來,receive()將一直等待,直到收到一個數(shù)據(jù)報為止。DatagramPacket packet=new DatagramPacket(buf, 256);Socket.receive (packet);發(fā)送數(shù)據(jù)前,也要先生成一個新的DatagramPacket對象,這時要使用上面的第二種構(gòu)造方法,在給出存放發(fā)送數(shù)據(jù)的緩沖區(qū)的同時,還要給出完整的目的地址,包括IP地址和端口號。發(fā)送數(shù)據(jù)是通過DatagramSocket的方法send()實現(xiàn)的,send()根據(jù)數(shù)據(jù)報的目的地址來尋徑,以傳遞數(shù)據(jù)報。DatagramPacket packet=new DatagramPacket(buf, length, address, port);Socket.send(packet);在構(gòu)造數(shù)據(jù)報時,要給出InetAddress類參數(shù)。類InetAddress在包中定義,用來表示一個Internet地址,我們可以通過它提供的類方法getByName()從一個表示主機名的字符串獲取該主機的IP地址,然后再獲取相應(yīng)的地址信息。基于UDP的簡單的Client/Server程序設(shè)計有了上面的知識,我們就可以來構(gòu)件一個基于UDP的C/S 網(wǎng)絡(luò)傳輸模型1. 客戶方程序 QuoteClient.javaimport java.io.*;import .*;import java.util.*;public class QuoteClient public static void main(String args) throws IOException if(args.length!=1) /如果啟動的時候沒有給出Server的名字,那么出錯退出System.out.println(Usage:java QuoteClient ); /打印出錯信息return; /返回DatagramSocket socket=new DatagramSocklet(); /創(chuàng)建數(shù)據(jù)報套接字Byte buf=new byte256; /創(chuàng)建緩沖區(qū)InetAddress address=InetAddress.getByName(args 0); /由命令行給出的第一個參數(shù)默認(rèn)為Server的名字,通過它得到Server的IP信息DatagramPacket packet=new DatagramPacket (buf, buf.length, address, 4445);/創(chuàng)建DatagramPacket對象socket.send(packet); /發(fā)送packet=new DatagramPacket(buf,buf.length); /創(chuàng)建新的DatagramPacket對象,用來接收數(shù)據(jù)報socket.receive(packet); /接收String received=new String(packet.getData(); /根據(jù)接收到的字節(jié)數(shù)組生成相應(yīng)的字符串System.out.println(Quote of the Moment:+received ); /打印生成的字符串socket.close(); /關(guān)閉套接口2. 服務(wù)器方程序:QuoteServer.javapublic class QuoteServerpublic static void main(String args) throws java.io.IOException new QuoteServerThread().start(); /啟動一個QuoteServerThread線程3. 程序QuoteServerThread.javaimport java.io.*;import .*;import java.util.*;/服務(wù)器線程public class QuoteServerThread extends Threadprotected DatagramSocket socket=null; /記錄和本對象相關(guān)聯(lián)的DatagramSocket對象protected BufferedReader in=null; /用來讀文件的一個Readerprotected boolean moreQuotes=true; /標(biāo)志變量,是否繼續(xù)操作public QuoteServerThread() throws IOException /無參數(shù)的構(gòu)造函數(shù)this(QuoteServerThread); /以QuoteServerThread為默認(rèn)值調(diào)用帶參數(shù)的構(gòu)造函數(shù)public QuoteServerThread(String name) throws IOException super(name); /調(diào)用父類的構(gòu)造函數(shù)socket=new DatagramSocket(4445); /在端口4445創(chuàng)建數(shù)據(jù)報套接字tryin= new BufferedReader(new FileReader( one-liners.txt);/打開一個文件,構(gòu)造相應(yīng)的BufferReader對象catch(FileNotFoundException e) /異常處理System.err.println(Could not open quote file. Serving tim
溫馨提示
- 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)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 金融服務(wù)居間合同委托書
- 物業(yè)服務(wù)外包合同
- 鍋爐購銷合同書
- 車輛租賃保險服務(wù)合同
- 語言編程及算法操作手冊
- 水產(chǎn)養(yǎng)殖與漁業(yè)技術(shù)作業(yè)指導(dǎo)書
- 軟件外包業(yè)軟件開發(fā)與項目管理流程優(yōu)化研究
- 綠色農(nóng)業(yè)生產(chǎn)技術(shù)方案
- 保姆雇傭勞動合同書
- 新夫妻離婚協(xié)議書參考樣板
- 藥膳與食療試題及答案高中
- 北京市西城區(qū)2024-2025學(xué)年八年級上學(xué)期期末考試數(shù)學(xué)試卷含答案
- 2025年南京信息職業(yè)技術(shù)學(xué)院高職單招數(shù)學(xué)歷年(2016-2024)頻考點試題含答案解析
- 二零二五年度海外市場拓展合作協(xié)議4篇
- 2024年湖南汽車工程職業(yè)學(xué)院單招職業(yè)技能測試題庫標(biāo)準(zhǔn)卷
- 2025中國鐵塔集團安徽分公司招聘29人高頻重點提升(共500題)附帶答案詳解
- 2025年河北省農(nóng)村信用社招聘歷年高頻重點提升(共500題)附帶答案詳解
- 手術(shù)室植入物的管理
- 電力供電系統(tǒng)試驗調(diào)試和聯(lián)調(diào)方法
- 食品經(jīng)營許可證主要設(shè)備設(shè)施布局圖及操作流程
- Unit6AtthesnackbarStorytimeDiningwithdragons(課件)譯林版英語四年級上冊
評論
0/150
提交評論