版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
PAGE340PAGE341第14章Java網(wǎng)絡(luò)編程技術(shù)網(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協(xié)議主要負(fù)責(zé)網(wǎng)絡(luò)主機(jī)的定位,由IP地址可以唯一地確定Internet上的一臺(tái)主機(jī);而TCP協(xié)議實(shí)現(xiàn)可靠的數(shù)據(jù)傳輸。目前較為流行的網(wǎng)絡(luò)編程模型是客戶(hù)機(jī)/服務(wù)器(C/S)模式,即通信的一方作為服務(wù)器等待客戶(hù)機(jī)提出請(qǐng)求并予以響應(yīng);客戶(hù)機(jī)則在需要服務(wù)時(shí)向服務(wù)器提出申請(qǐng)。服務(wù)器一般作為守護(hù)進(jìn)程始終運(yùn)行,監(jiān)聽(tīng)服務(wù)器的網(wǎng)絡(luò)端口,一旦某個(gè)客戶(hù)機(jī)提出請(qǐng)求,服務(wù)器就會(huì)為每個(gè)客戶(hù)機(jī)創(chuàng)建并啟動(dòng)一個(gè)服務(wù)線程來(lái)響應(yīng)該客戶(hù)機(jī),同時(shí)自己繼續(xù)監(jiān)聽(tīng)服務(wù)器的網(wǎng)絡(luò)端口,使后來(lái)的客戶(hù)機(jī)也能及時(shí)得到服務(wù)。14.1使用URLURL(UniformResourceLocator,統(tǒng)一資源定位器)主要用來(lái)對(duì)Internet上的信息進(jìn)行定位。瀏覽器借助它來(lái)查找Web上的信息。實(shí)際上,Web通過(guò)URL和HTML對(duì)所有的網(wǎng)絡(luò)資源定位。在Java的網(wǎng)絡(luò)編程中,程序員使用URL類(lèi)庫(kù),獲取Internet上的信息。14.1.1URL組成URL的兩種語(yǔ)句格式:1./2.:80/index.htm從上面的URL格式可以看出,URL由以下4個(gè)部分組成:協(xié)議(http)。指網(wǎng)絡(luò)連接用到的協(xié)議,如,本例的http是超文本協(xié)議,http不是唯一的協(xié)議,常見(jiàn)的協(xié)議還有FTP、Gopher等。其中的冒號(hào):將協(xié)議與URL的其他部分隔開(kāi)。主機(jī)名或其IP地址()。該項(xiàng)位于雙斜線(//)和單斜線(/)之間,其中的冒號(hào)(:)是可選部。如,本例的/或:80表示了主機(jī)名。端口號(hào)(80)。它是可選的參數(shù),它位于主機(jī)名和右邊的單斜線(/)之間(HTTP協(xié)議的默認(rèn)端口為80,所以“:80”可以不寫(xiě)),可以是別的數(shù)字組成端口號(hào)。網(wǎng)頁(yè)文件及所在的目錄(index.htm)。網(wǎng)頁(yè)文件及目錄是瀏覽器要查找的網(wǎng)頁(yè)資源。如index.html或index.htm文件。14.1.2URL類(lèi)在Java中URL類(lèi)的繼承關(guān)系如下:publicfinalclassURLextendsObjectimplementsSerializable1.URL的構(gòu)造方法URL類(lèi)有多個(gè)構(gòu)造方法,它們都可能拋出MalformedURLException異常。(1)URL(StringurlSpecifier)的使用格式URLurl=newURL("/");(2)URL(Stringprotocol,StringhostName,intport,Stringpath)的使用格式URLurl=newURL("http","",80,"nba");(3)URL(Stringprotocol,StringhostName,Stringpath)的使用格式URLurl=newURL("http","","nba");(4)URL(URLcontext,Stringspec)使用一個(gè)已經(jīng)存在的URL創(chuàng)建一個(gè)新的URLURLurl1=newURL("/");//構(gòu)造url1對(duì)象URLurl2=newURL(url,"nba");//利用上面的url1對(duì)象和一個(gè)字符串為參數(shù)創(chuàng)建新的url2對(duì)象2.URL的實(shí)用方法booleanequals(Objectobj):比較兩個(gè)URL是否相同。StringgetAuthority():獲得URL的授權(quán)部分。ObjectgetContent():獲得URL的內(nèi)容。ObjectgetContent(Class[]classes):獲得URL的內(nèi)容。intgetDefaultPort():獲得URL中的默認(rèn)端口號(hào)。StringgetFile():獲得URL中的網(wǎng)頁(yè)文件名。StringgetHost():獲得URL中的主機(jī)名。StringgetPath():獲得URL中網(wǎng)頁(yè)所在的路徑。intgetPort():獲得URL中的端口號(hào),若沒(méi)有設(shè)置端口號(hào)則返回-1。StringgetProtocol():獲得URL所用的協(xié)議名稱(chēng)。StringgetQuery():獲得URL的查詢(xún)部分。StringgetRef():獲得URL的錨點(diǎn)(也稱(chēng)為“引用”)。StringgetUserInfo():獲得URL的UserInfo部分。inthashCode():創(chuàng)建一個(gè)適合散列表索引的整數(shù)。InputStreamopenStream():打開(kāi)URL的鏈接。并返回一個(gè)用于從該鏈接讀入的InputStream流。booleansameFile(URLother):比較兩個(gè)URL,不包括片段部分。StringtoExternalForm():將URL轉(zhuǎn)換為字符串格式。StringtoString():構(gòu)造URL的字符串表示形式。URItoURI():返回與URL等效的URI。3.URL應(yīng)用【例14.1】創(chuàng)建一個(gè)URL實(shí)例,然后檢查它的相關(guān)屬性。程序名:Example14_1.java?!境绦蛟创a】import.*;classExample14_1{ publicstaticvoidmain(Stringargs[])throwsMalformedURLException{ try{ URLurl=newURL(""); //創(chuàng)建一個(gè)URL對(duì)象 System.out.println("授權(quán):"+url.getAuthority());//檢查它的授權(quán)部分 System.out.println("協(xié)議名稱(chēng):"+url.getProtocol());//獲得此URL的協(xié)議名 System.out.println("默認(rèn)端口號(hào):"+url.getDefaultPort());//獲得默認(rèn)端口號(hào) System.out.println("主機(jī)名:"+url.getHost()); //獲得此URL的主機(jī)名 System.out.println("文件名:"+url.getFile()); //獲得此URL的文件名 System.out.println("Ext:"+url.toExternalForm()); System.out.println("字符串表示形式:"+url.toString()); } catch(MalformedURLExceptionex){ System.out.println("fail!"); } }}【例14.2】在Applet的文本框中輸入一個(gè)網(wǎng)址,單擊search(搜索)按鈕后鏈接到該網(wǎng)址相對(duì)應(yīng)的頁(yè)面。程序名:Example14_2.java【程序說(shuō)明】要在Applet中鏈接到其它Web頁(yè)面,可使用下面的代碼來(lái)實(shí)現(xiàn)。getAppletContext().showDocument(url);//執(zhí)行該方法,轉(zhuǎn)向url頁(yè)面因?yàn)間etAppletContext()方法是在Applet類(lèi)中定義的,由showDocument()定位到另一個(gè)Web頁(yè)面?!境绦蛟创a】importjava.awt.*;importjava.awt.event.*;importjavax.swing.*;import.*;importjava.io.*;importjava.applet.*; publicclassShowWebPageextendsJAppletimplementsActionListener{ privatestaticfinallongserialVersionUID=1L; privateJLabellfn=newJLabel("URLaddress"); privateJTextFieldtfu=newJTextField(20);//網(wǎng)址輸入框 privateJButtonsearb=newJButton("search");//搜索按鈕 /**初始化界面*/ publicvoidinit(){ Containerc=getContentPane();//獲取底層容器 searb.addActionListener(this);//為按鈕注冊(cè)監(jiān)聽(tīng)器 c.setLayout(newFlowLayout());//設(shè)置布局 c.add(lfn);//添加標(biāo)簽 c.add(tfu);//添加網(wǎng)址輸入文本框 c.add(searb);//添加Search(搜索)按鈕 } /**響應(yīng)按鈕事件*/ publicvoidactionPerformed(ActionEvente){ Strings=tfu.getText();//獲取輸入框內(nèi)容 try{ URLu=newURL(s);//利用網(wǎng)址輸入框中的內(nèi)容創(chuàng)建一個(gè)URL對(duì)象 getAppletContext().showDocument(u);//顯示指定URL的網(wǎng)頁(yè) }catch(MalformedURLExceptionex){ showStatus(s+"fileformaterror!");} }}14.2Socket套接字14.2.1Socket的含義Socket描述了網(wǎng)絡(luò)上運(yùn)行的兩個(gè)程序間實(shí)現(xiàn)通信的任一端。它既可以接收請(qǐng)求,也可以發(fā)送請(qǐng)求。利用它可以方便地編寫(xiě)網(wǎng)絡(luò)上傳遞數(shù)據(jù)的程序。在Java中,有專(zhuān)門(mén)的Socket類(lèi)來(lái)處理用戶(hù)的請(qǐng)求和響應(yīng)。利用Socket類(lèi)的方法,就可以實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)之間的通信。在Java中,Socket可以理解為客戶(hù)端或者服務(wù)器端的一個(gè)特殊的對(duì)象。這個(gè)對(duì)象有兩個(gè)關(guān)鍵的方法:一個(gè)是getInputStream()方法;另一個(gè)是getOutputStream()方法。getInputStream()方法可以得到一個(gè)輸入流??蛻?hù)端的Socket對(duì)象上的getInputStream()方法得到的輸入流就是從服務(wù)器端發(fā)送回來(lái)的數(shù)據(jù)流。getOutputStream()方法得到一個(gè)輸出流??蛻?hù)端的Socket對(duì)象上的getOutputStream()方法返回的輸出流就是將要發(fā)送到服務(wù)器端的數(shù)據(jù)流(其實(shí)是一個(gè)緩沖區(qū),暫時(shí)存儲(chǔ)將要發(fā)送到服務(wù)器端的數(shù)據(jù))。下面介紹Socket實(shí)現(xiàn)網(wǎng)絡(luò)通信的機(jī)制。圖14-1服務(wù)器與客戶(hù)機(jī)進(jìn)行通信的方式1.建立服務(wù)器端套接字Java中有一個(gè)ServerSocket類(lèi),專(zhuān)門(mén)用來(lái)建立服務(wù)器端的套接字。可以用服務(wù)器需要使用的端口號(hào)作為參數(shù)來(lái)創(chuàng)建服務(wù)器套接字。ServerSocketserver=newServerSocket(8000);這條語(yǔ)句創(chuàng)建了一個(gè)服務(wù)器套接字server。該服務(wù)器使用8000號(hào)端口監(jiān)聽(tīng)客戶(hù)機(jī)請(qǐng)求。2.在服務(wù)器端為每個(gè)客戶(hù)機(jī)建立代理套接字當(dāng)一個(gè)客戶(hù)端程序要求與服務(wù)器建立一個(gè)Socket連接時(shí),在服務(wù)器端,服務(wù)器套接字便會(huì)為客戶(hù)機(jī)建立一個(gè)客戶(hù)機(jī)代理套接字connectToClient,通過(guò)該套接字與客戶(hù)機(jī)端的Socket套接字建立連接。(1)在服務(wù)器端為客戶(hù)機(jī)建立代理套接字的格式如下:SocketconnectToClient=server.accept();//代理套接字connectToClient(2)服務(wù)器端從客戶(hù)端收到的輸入流s_in(也就是客戶(hù)端的輸出流)的其格式如下:BufferedReaders_in=newBufferedReader(newInputStreamReader(connectToClient.getInputStream()));(3)服務(wù)器端傳給客戶(hù)端的輸出流s_out(也就是客戶(hù)端的輸入流)的格式如下:PrintWriterout=newPrintWriter(connectToClient.getOutputStream(),true);隨后,就可以使用s_in.readLine()方法得到客戶(hù)端的輸入;也可以使用s_out.println()方法向客戶(hù)端發(fā)送數(shù)據(jù)。在所有通信結(jié)束以后應(yīng)該關(guān)閉這兩個(gè)數(shù)據(jù)流。關(guān)閉的順序是先關(guān)閉輸出流,再關(guān)閉輸入流,即依次調(diào)用out.close();和in.close();方法。3.建立客戶(hù)端套接字(Socket)客戶(hù)端只需用服務(wù)器所在機(jī)器的IP以及服務(wù)器的端口號(hào)作為參數(shù)即可創(chuàng)建一個(gè)客戶(hù)端套接字(connectToServer)。假設(shè)服務(wù)器的端口號(hào)是8000。(1)建立客戶(hù)機(jī)的套接字格式如下:SocketconnectToServer=newSocket("服務(wù)器IP地址",8000);或者SocketconnectToServer=newSocket("服務(wù)器主機(jī)名",8000);(2)客戶(hù)端從服務(wù)器端收到的輸入流in(也就是服務(wù)器端的輸出流)的格式如下:InputStreamin=connectToServer.getInputStream();(3)客戶(hù)端向服務(wù)器端發(fā)送的輸出流out(也就是服務(wù)器端的輸入流)的格式如下:OutputStreamout=connectToServer.getOutputStream();14.2.2Socket的應(yīng)用【例14.3】實(shí)現(xiàn)客戶(hù)機(jī)和服務(wù)器相互交替接收對(duì)方所寫(xiě)入的信息,實(shí)現(xiàn)兩者間的通信。程序名:MyClient.java&&MyServer.java【程序源代碼】/**客戶(hù)端程序:MyClient.Java*/packagesocket;import.*;importjava.io.*;publicclassMyClient{ staticSocketserver; publicstaticvoidmain(String[]args)throwsIOException{ try{ /**向本機(jī)的5678端口發(fā)出客戶(hù)機(jī)請(qǐng)求*由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象*由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象*/ server=newSocket(InetAddress.getLocalHost(),5678); BufferedReaderin=newBufferedReader(newInputStreamReader(server.getInputStream())); PrintWriterout=newPrintWriter(server.getOutputStream()); /**由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對(duì)象作為用戶(hù)輸入信息流*/ System.out.println("輸入發(fā)送信息:"); BufferedReaderwt=newBufferedReader(newInputStreamReader(System.in)); /**利用循環(huán)不斷發(fā)送數(shù)據(jù)*/ while(true){ Stringstr=wt.readLine();//從系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備讀入一字符串 out.println(str);//將從系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備讀入的字符串輸出到Server out.flush();//刷新輸出流,使Server馬上收到該字符串 if(str.equals("end")){ break;} System.out.println("Server說(shuō):"+in.readLine());//輸出接收到信息 } out.close();//關(guān)閉Socket輸出流 in.close();//關(guān)閉Socket輸入流 server.close();//關(guān)閉Socket }catch(Exceptione){ System.out.println("error:"+e); } }} /**服務(wù)器端程序:MyServer.java*/packagesocket;//類(lèi)包importjava.io.*;import.*;publicclassMyServer{ publicstaticvoidmain(String[]args)throwsIOException{ try{ //創(chuàng)建一個(gè)ServerSocket在端口5678監(jiān)聽(tīng)客戶(hù)機(jī)請(qǐng)求 ServerSocketserver=newServerSocket(5678); /**使用accept()阻塞等待客戶(hù)機(jī)請(qǐng)求,*有客戶(hù)機(jī)請(qǐng)求到來(lái)則產(chǎn)生一個(gè)Socket對(duì)象,并繼續(xù)執(zhí)行*/ Socketclient=server.accept(); //顯示連接到的客戶(hù)機(jī)IP System.out.println("connectto:"+client.getInetAddress()); //由系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備構(gòu)造BufferedReader對(duì)象作為用戶(hù)輸入信息流 BufferedReaderwt=newBufferedReader(newInputStreamReader(System.in)); //由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的BufferedReader對(duì)象 BufferedReaderin=newBufferedReader(newInputStreamReader(client.getInputStream())); //由Socket對(duì)象得到輸出流,并構(gòu)造PrintWriter對(duì)象 PrintWriterout=newPrintWriter(client.getOutputStream()); /**利用循環(huán)不斷接收數(shù)據(jù)*/ while(true){ Stringstr1=in.readLine(); //在標(biāo)準(zhǔn)輸出設(shè)備上打印從客戶(hù)端讀入的字符串 System.out.println("Client說(shuō):"+str1); if(str1.equals("end"))break;//若客戶(hù)機(jī)輸入"end",則斷開(kāi)與客戶(hù)機(jī)的連接 Stringstr2=wt.readLine(); out.println(str2);//將從系統(tǒng)標(biāo)準(zhǔn)輸入設(shè)備讀入的字符串輸出到客戶(hù)機(jī) out.flush();//刷新輸出流,使服務(wù)器馬上收到該字符串 } out.close();//關(guān)閉Socket輸出流 in.close();//關(guān)閉Socket輸入流 client.close();//關(guān)閉Socket server.close();//關(guān)閉ServerSocket }catch(Exceptione){ System.out.println("error:"+e); } }}【程序運(yùn)行結(jié)果】將上面兩個(gè)程序放在Socket目錄下編譯,先運(yùn)行服務(wù)器端,然后運(yùn)行客戶(hù)端,結(jié)果如圖14-2、圖14-3所示。圖14-2例14.3客戶(hù)端程序運(yùn)行結(jié)果圖14-3例14.3服務(wù)器端程序運(yùn)行結(jié)果【例14.4】Socket的多線程通信。程序名:Cal_Client.java&&Cal_Server.java【程序說(shuō)明】在本例中,在客戶(hù)機(jī)輸入三角形3條邊的長(zhǎng)度并發(fā)送給服務(wù)器;服務(wù)器把計(jì)算出的三角形面積返回給客戶(hù)機(jī)??梢詫⒂?jì)算量大的工作放在服務(wù)器端,客戶(hù)端則負(fù)責(zé)計(jì)算量小的工作,實(shí)現(xiàn)客戶(hù)機(jī)、服務(wù)器交互計(jì)算,從而完成任務(wù)。套接字連接中涉及到輸入流和輸出流操作,為了不影響做其他的事情,應(yīng)把套接字連接放在一個(gè)單獨(dú)的線程中。另外,服務(wù)器端為每個(gè)客戶(hù)機(jī)創(chuàng)建并啟動(dòng)一個(gè)服務(wù)線程?!境绦蛟创a】/**客戶(hù)端代碼:Cal_Client.Java**/import.*;importjava.io.*;importjava.awt.*;importjava.awt.event.*;importjava.applet.*;importjavax.swing.*;publicclassCal_ClientextendsJAppletimplementsRunnable,ActionListener{ JButtonb_calc; //計(jì)算按鈕 TextFieldb_edge,b_result;//b_edg是3條邊輸入的文本框;b_result是結(jié)果文本框 Socketsocket=null; //連接套接字 DataInputStreamin=null; //輸入數(shù)據(jù)流 DataOutputStreamout=null; //輸出數(shù)據(jù)流 Threadthread; //負(fù)責(zé)接收計(jì)算結(jié)果的線程 /**下面初始化界面*/ publicvoidinit()
{ setLayout(newGridLayout(2,2)); JPanelp1=newJPanel(),p2=newJPanel(); b_calc=newJButton("b_calc"); b_edge=newTextField(12); b_result=newTextField(12); p1.add(newJLabel("輸入三角形三邊的長(zhǎng)度,用逗號(hào)或空格分隔:")); p1.add(b_edge);p2.add(newJLabel("計(jì)算結(jié)果:")); p2.add(b_result);p2.add(b_calc); b_calc.addActionListener(this); add(p1);add(p2); /**創(chuàng)建連接套接字,并構(gòu)造相應(yīng)的輸入輸出流對(duì)象*/ Try { /**向本機(jī)的4331端口發(fā)出客戶(hù)請(qǐng)求*由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的DataInputStream對(duì)象*由Socket對(duì)象得到輸出流,并構(gòu)造DataOutputStream對(duì)象*/ socket=newSocket("localhost",4331); in=newDataInputStream(socket.getInputStream()); out=newDataOutputStream(socket.getOutputStream()); }catch(IOExceptione){}/**創(chuàng)建線程,負(fù)責(zé)接收服務(wù)器信息*/ if(thread==null){thread=newThread(this);thread.start();} } /**線程調(diào)用方法,負(fù)責(zé)接收運(yùn)算結(jié)果*/ publicvoidrun(){ Strings=null; while(true) { try{//利用Socket輸入流對(duì)象接收服務(wù)器運(yùn)算結(jié)果,在讀取到信息之前處于堵塞狀態(tài)。 s=in.readUTF(); b_result.setText(s); }catch(IOExceptione){b_result.setText("與服務(wù)器已斷開(kāi)"); break;} } } /**響應(yīng)動(dòng)作事件,負(fù)責(zé)將數(shù)據(jù)發(fā)送到服務(wù)器端*/ publicvoidactionPerformed(ActionEvente) { if(e.getSource()==b_calc) { Strings=b_edge.getText(); if(s!=null) {try {//將三角形的邊長(zhǎng)數(shù)據(jù)通過(guò)Socket輸出流對(duì)象發(fā)送到服務(wù)器 out.writeUTF(s); } catch(IOExceptione1){} } } }}/**對(duì)應(yīng)的HTML文檔:*<APPLETCODE=Cal_Client.classWIDTH=500HEIGHT=500>*</APPLET>*/ /**服務(wù)器端代碼:Cal_Server.java**/importjava.io.*;import.*;importjava.util.*;publicclassCal_Server{ publicstaticvoidmain(Stringargs[]){ ServerSocketserver=null; Server_threadthread; Socketyou=null; while(true) { try { server=newServerSocket(4331); } catch(IOExceptione1){System.out.println("正在監(jiān)聽(tīng)");//ServerSocket對(duì)象不能重復(fù)創(chuàng)建} try { you=server.accept(); System.out.println("客戶(hù)的地址:"+you.getInetAddress()); } catch(IOExceptione){System.out.println("正在等待客戶(hù)"); } if(you!=null){newServer_thread(you).start();//為每個(gè)客戶(hù)啟動(dòng)一個(gè)專(zhuān)門(mén)的線程} else{continue; } } }}/**線程類(lèi),負(fù)責(zé)計(jì)算面積工作**/classServer_threadextendsThread{ Socketsocket=null; //連接套接字 DataInputStreamin=null; //數(shù)據(jù)輸入流 DataOutputStreamout=null; //數(shù)據(jù)輸出流 Strings=null; //待發(fā)送的運(yùn)算結(jié)果 /**利用Cal_Server類(lèi)中的Socket對(duì)象構(gòu)造線程對(duì)象**/ publicServer_thread(Sockett){ socket=t; try{ //由Socket對(duì)象得到輸入流,并構(gòu)造相應(yīng)的DataInputStream對(duì)象 in=newDataInputStream(socket.getInputStream()); //由Socket對(duì)象得到輸出流,并構(gòu)造DataOutputStream對(duì)象 out=newDataOutputStream(socket.getOutputStream()); } catch(IOExceptione){ } } /**線程調(diào)用方法,負(fù)責(zé)計(jì)算面積,并將計(jì)算結(jié)果發(fā)給客戶(hù)端**/ publicvoidrun(){ while(true) { doublea[]=newdouble[3]; inti=0; try{ /**利用Socket輸入流對(duì)象接收客戶(hù)端傳來(lái)的邊長(zhǎng)參數(shù),*在讀取到信息之前處于堵塞狀態(tài)*/ s=in.readUTF(); /**判斷、分析傳來(lái)的參數(shù),若格式錯(cuò)誤則向客戶(hù)端提示錯(cuò)誤, *正確則進(jìn)行面積計(jì)算并返回給客戶(hù)端 */ StringTokenizerfenxi=newStringTokenizer(s,","); while(fenxi.hasMoreTokens()) { Stringtemp=fenxi.nextToken(); try { a[i]=Double.valueOf(temp).doubleValue(); i++; } catch(NumberFormatExceptione) {out.writeUTF("請(qǐng)輸入數(shù)字字符");} } doublep=(a[0]+a[1]+a[2])/2.0; /**將面積通過(guò)Socket輸出流對(duì)象發(fā)送給客戶(hù)端*/ out.writeUTF("" +Math.sqrt(p*(p-a[0])*(p-a[1])*(p-a[2]))); sleep(2); } catch(InterruptedExceptione){ } catch(IOExceptione){System.out.println("客戶(hù)離開(kāi)");break;} }//while語(yǔ)句結(jié)束 }//方法結(jié)束}【程序運(yùn)行結(jié)果】程序運(yùn)行結(jié)果如圖14-4、圖14-5所示。圖14-4例14.4客戶(hù)端程序運(yùn)行結(jié)果圖14-5例14.4服務(wù)器端程序運(yùn)行結(jié)果14.3InetAddress類(lèi).InetAddress類(lèi)封裝了IP地址。該類(lèi)的聲明格式如下:publicfinalclassInetAddressextendsobjectimplementsSerializable該類(lèi)里有兩個(gè)成員變量:hostName(數(shù)據(jù)類(lèi)型是String)和address(數(shù)據(jù)類(lèi)型是int),即主機(jī)名和IP地址。這兩個(gè)成員變量是的訪問(wèn)權(quán)限是私有的(private)。14.3.1InetAddress類(lèi)1.獲取InetAddress對(duì)象InetAddress類(lèi)沒(méi)有構(gòu)造方法??梢酝ㄟ^(guò)該類(lèi)的類(lèi)方法獲取其實(shí)例。(1)publicstaticInetAddressgetLocalHost()該方法獲得本地機(jī)器的InetAddress對(duì)象,當(dāng)查找不到本地機(jī)器的地址時(shí)將拋出一個(gè)UnknownHostException異常。示范代碼如下:try{InetAddressaddress=InetAddress.getLocalHost();…//其他處理代碼}catch(UnknownExceptione){…//異常處理代碼}(2)publicstaticInetAddressgetByName(Stringhost)該方法獲得host(計(jì)算機(jī)的域名)指定的InetAddress對(duì)象。如果找不到主機(jī)將觸發(fā)UnknownHostException異常。示范代碼如下:try{InetAddressaddress=InetAddress.getByName(host);…//其他處理代碼}catch(UnknownExceptione){…//異常處理代碼}(3)publicstaticInetAddress[]getAllByName(Stringhost)該方法把網(wǎng)絡(luò)上的一組計(jì)算機(jī)的InetAddress對(duì)象保存在數(shù)組中。出錯(cuò)了同樣會(huì)拋出UnknownException異常。示范代碼如下:try{InetAddressaddress=InetAddress.getAllByName(host);…//其他處理代碼}catch(UnknownExceptione){…//異常處理代碼}提示:InteAddress類(lèi)有一個(gè)getAddress()方法,該方法將IP地址以網(wǎng)絡(luò)字節(jié)順序作為字節(jié)數(shù)組返回。當(dāng)前IP只有4個(gè)字節(jié),但是當(dāng)實(shí)行IPV6時(shí)就有6個(gè)字節(jié)了。如果需要知道數(shù)組的長(zhǎng)度,可以使用數(shù)組的length字段。getAddress()方法的一般性用法如下:InetAddressinetaddress=InetAddress.getLocalHost();byte[]address=inetaddress.getAddress();2.InetAddress類(lèi)的實(shí)用方法(1)publicStringgetHostName()該方法返回主機(jī)名(一個(gè)字符串)。如果要查詢(xún)的機(jī)器沒(méi)有主機(jī)名,則該方法就返回主機(jī)的IP地址。一般的使用格式如下:InetAddressinetadd=InetAddress.getLocalHost();Stringlocalname=inetadd.getHostName();(2)publicStringgetHostAddress()該方法返回主機(jī)的IP地址(字符串格式)。(3)publicStringtoString()該方法返回主機(jī)名和IP地址(字符串格式),其具體形式為“主機(jī)名/點(diǎn)分地址”。如果一個(gè)InetAddress對(duì)象沒(méi)有主機(jī)名,則返回IP地址(字符串格式)。14.3.2InetAddress類(lèi)的應(yīng)用【例14.5】查詢(xún)IP地址是IPV4還是IPV6,以及地址的類(lèi)型(A,B,C,D)。程序名:Example14_5.java【程序源代碼】import.*;importjava.io.*;publicclassExample14_5{ publicstaticvoidmain(Stringargs[]){ try{ //獲得本地IP地址 InetAddressinetadd=InetAddress.getLocalHost(); //將IP地址以網(wǎng)絡(luò)字節(jié)順序作為字節(jié)數(shù)組返回 byte[]address=inetadd.getAddress(); if(address.length==4){ System.out.println("Theipversionisipv4"); intfirstbyte=address[0]; /** *由于返回的byte[]字節(jié)是無(wú)符號(hào)的,但是Java沒(méi)有無(wú)符號(hào)字節(jié)的基本數(shù) *據(jù)類(lèi)型,因此如果要對(duì)返回的字節(jié)進(jìn)行操作,必須要將int進(jìn)行適當(dāng)?shù)恼{(diào)整 */ if(firstbyte<0) firstbyte+=256; if((firstbyte&0x80)==0)//firstbyte<=126,對(duì)應(yīng)IP為A類(lèi)地址 System.out.println("theipclassisA"); //128<=firstbyte<=191,對(duì)應(yīng)IP為B類(lèi)地址 elseif((firstbyte&0xC0)==0x80) System.out.println("TheipclassisB"); //192<=firstbyte<=223,對(duì)應(yīng)IP為C類(lèi)地址 elseif((firstbyte&0xE0)==0xC0) System.out.println("TheipclassisC"); //224<=firstbyte<=239,對(duì)應(yīng)IP為D類(lèi)地址 elseif((firstbyte&0xF0)==0xE0) System.out.println("TheipclassisD"); //240<=firstbyte<=255,對(duì)應(yīng)IP為E類(lèi)地址 elseif((firstbyte&0xF8)==0xF0) System.out.println("TheipclassisE"); }elseif(address.length==16) System.out.println("Theipversionisipv6"); }catch(Exceptione){} }}【程序運(yùn)行結(jié)果】Theipversionisipv4TheipclassisC【例14.6】獲取域名是和的主機(jī)域名及ip地址程序名:Example14_6【程序源代碼】import.*;publicclassExample14_6{ publicstaticvoidmain(Stringargs[]) { try { InetAddressaddress_1=InetAddress.getByName(""); System.out.println(address_1.toString()); InetAddressaddress_2=InetAddress.getByName(""); System.out.println(address_2.toString()); } catch(Exceptione){ System.out.println("無(wú)法找到"); } }}14.4UDP數(shù)據(jù)報(bào)在TCP/IP協(xié)議包含TCP協(xié)議和UDP協(xié)議。相對(duì)而言,UDP的應(yīng)用不如TCP廣泛,幾個(gè)標(biāo)準(zhǔn)的應(yīng)用層協(xié)議HTTP、FTP、SMTP等使用的都是TCP協(xié)議。但是,隨著計(jì)算機(jī)網(wǎng)絡(luò)的發(fā)展,UDP協(xié)議正越來(lái)越顯示出其威力,尤其是在需要很強(qiáng)的實(shí)時(shí)交互性的場(chǎng)合,如網(wǎng)絡(luò)游戲、視頻會(huì)議等,UDP更是顯示出極強(qiáng)的威力。下面就來(lái)介紹Java環(huán)境下如何實(shí)現(xiàn)UDP網(wǎng)絡(luò)傳輸。14.4.1什么是Datagram所謂數(shù)據(jù)報(bào)(Datagram)就像日常生活中的郵件系統(tǒng)一樣,不能確??煽康丶牡剑欢嫦蜴溄拥腡CP就好比是電話,雙方能肯定對(duì)方接收到了信息。TCP和UDP的區(qū)別:TCP可靠,傳輸大小無(wú)限制,但是需要時(shí)間建立連接,差錯(cuò)控制開(kāi)銷(xiāo)大;UDP不可靠,差錯(cuò)控制開(kāi)銷(xiāo)較小,傳輸大小限制在64KB以下,不需要建立連接。14.4.2Datagram通信包中提供了兩個(gè)類(lèi)(DatagramSocket和DatagramPacket)支持?jǐn)?shù)據(jù)報(bào)通信。其中,DatagramSocket用于在程序之間建立通信連接;DatagramPacket則用來(lái)表示一個(gè)數(shù)據(jù)報(bào)。1.DatagramSocket的構(gòu)造方法DatagramSocket();//構(gòu)造方法調(diào)用時(shí)都要拋出SocketException異常。DatagramSocket(intprot);構(gòu)造方法調(diào)用時(shí)都要拋出SocketException異常。DatagramSocket(intport,InetAddressladdr);。其中,port指明Socket所使用的端口號(hào),如果未指明端口號(hào),則把Socket連接到本地主機(jī)上一個(gè)可用的端口;laddr指明一個(gè)可用的本地地址。給出端口號(hào)時(shí)要保證不發(fā)生端口沖突,否則會(huì)拋出SocketException異常。使用時(shí)的格式如下:try{DatagramSocketds1=DatagramSocekt();DatagramSocektds2=DatagramSocket(5678);DatagramSocektds3=DatagramSocket(5678,InetAddress.getByName(localhost).);…//其他處理代碼}catch(SocketExceptione){…//異常處理代碼}用數(shù)據(jù)報(bào)方式編寫(xiě)Client/Server程序時(shí),無(wú)論在客戶(hù)端還是服務(wù)器端,首先都要建立一個(gè)DatagramSocket對(duì)象,用來(lái)接收或發(fā)送數(shù)據(jù)報(bào),然后使用DatagramPacket對(duì)象作為傳輸數(shù)據(jù)的載體。2.DatagramPacket的構(gòu)造方法DatagramPacket(bytebuf[],intlength);。DatagramPacket(bytebuf[],intlength,InetAddressaddr,intport);。DatagramPacket(byte[]buf,intoffset,intlength);。DatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddress,intport);。其中,buf中存放數(shù)據(jù)報(bào)數(shù)據(jù),length為數(shù)據(jù)報(bào)中數(shù)據(jù)的長(zhǎng)度,addr和port指明目的地址,offset指明了數(shù)據(jù)報(bào)的位移量。3.基于UDP的通信模式(1)將數(shù)據(jù)打包(稱(chēng)為數(shù)據(jù)包),就像將信件裝入信封一樣,然后將數(shù)據(jù)包發(fā)往目的地。在發(fā)送數(shù)據(jù)包前,先要?jiǎng)?chuàng)建一個(gè)DatagramPacket對(duì)象,這時(shí)就要用到上文介紹的構(gòu)造方法Datagrampacker(bytebuf[],intlength,InetAddressaddr,intport);在給出存放發(fā)送數(shù)據(jù)的緩沖區(qū)的同時(shí),還要給出完整的目的地址,包括IP地址和端口號(hào)。發(fā)送數(shù)據(jù)是通過(guò)DatagramSocket的方法send()實(shí)現(xiàn)的。send()根據(jù)數(shù)據(jù)報(bào)的目的地址來(lái)尋徑,以傳遞數(shù)據(jù)報(bào)。發(fā)送數(shù)據(jù)報(bào)的格式如下:try{InetAddressaddress=InetAddress.getByName("localhost");DatagramPacketdata_pack=newDatagramPacket(buffer,buffer.length,address,888);DatagramSocketmail_data=newDatagramSocket();mail_data.send(data_pack);//利用send()方法將指定的數(shù)據(jù)從端口888處發(fā)送出去…//其他處理代碼}catch(Exceptione){//異常處理代碼}(2)接收別人發(fā)來(lái)的數(shù)據(jù)包,好比接收信件一樣,然后查看數(shù)據(jù)包中的內(nèi)容。在接收數(shù)據(jù)前,應(yīng)該采用上面介紹的Datagrampacker(bytebuf[],intlength)方法創(chuàng)建一個(gè)DatagramPacket對(duì)象,給出接收數(shù)據(jù)的緩沖區(qū)及其長(zhǎng)度。然后調(diào)用DatagramSocket的方法receive()等待數(shù)據(jù)報(bào)的到來(lái)。receive()將一直等待,直到收到一個(gè)數(shù)據(jù)報(bào)為止。接收數(shù)據(jù)包的格式如下:try{DatagramSocketmail_data=newDatagramSocket(666);//從端口666處接收數(shù)據(jù)DatagramPacketdata_pack=newDatagramPacket(data,data.length);//data為指定接收數(shù)據(jù)的字節(jié)數(shù)組mail_data.receive(data_pack);//利用receive()方法等待接收數(shù)據(jù)…//其他處理代碼}catch(Exceptione){//異常處理代碼}14.4.3UDP數(shù)據(jù)報(bào)的應(yīng)用【例14.7】利用UDP實(shí)現(xiàn)網(wǎng)絡(luò)通信。程序名:UDP_ME.Java&&UDP_YOU.java【程序說(shuō)明】本例通過(guò)UDP數(shù)據(jù)報(bào)實(shí)現(xiàn)網(wǎng)絡(luò)通信。為了方便測(cè)試,本例的通信雙方都設(shè)置在本地主機(jī)上(同一臺(tái)機(jī)器)。讀者可以根據(jù)實(shí)際情況調(diào)整DatagramPacket對(duì)象,實(shí)現(xiàn)在不同主機(jī)之間進(jìn)行通信。【程序源代碼】/**UDP_ME端代碼:UDP_ME.Java*/packageudp;//類(lèi)包import.*;importjava.io.*;importjava.awt.*;importjava.awt.event.*;importjavax.swing.*;importjavax.swing.event.*;publicclassUDP_MEextendsJFrame{ publicUDP_ME(){ Chat_mecs=newChat_me(); getContentPane().add(cs); } publicstaticvoidmain(String[]args){ UDP_MEframe=newUDP_ME(); frame.setTitle("梁山伯界面"); frame.setSize(510,500); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }}classChat_meextendsJPanelimplementsRunnable,ActionListener{ JButtonsend;//發(fā)送按鈕 TextAreamsg_show;//信息顯示框 TextFieldmsg_send;//信息發(fā)送框 Threadthread=null;//負(fù)責(zé)接收數(shù)據(jù)的線程 /**初始化界面**/ publicChat_me(){ setLayout(null); send=newJButton("發(fā)送"); msg_show=newTextArea(); msg_send=newTextField(); JLabeljl=newJLabel("信息顯示區(qū)"); jl.setBounds(0,0,500,20); add(jl); /**添加信息顯示框到面板上*/ msg_show.setBounds(0,20,500,300); msg_show.setEditable(false); add(msg_show); JLabeljl1=newJLabel("信息發(fā)送區(qū)"); jl1.setBounds(0,320,500,20); add(jl1); /**添加信息發(fā)送框到面板上*/ msg_send.setBounds(0,340,400,80); add(msg_send); msg_send.addActionListener(this);//為信息發(fā)送框設(shè)置監(jiān)聽(tīng)器 /**添加發(fā)送按鈕到面板上*/ send.setBounds(400,360,100,40); add(send); send.addActionListener(this);//為發(fā)送按鈕設(shè)置監(jiān)聽(tīng)器 /**建立并啟動(dòng)線程,負(fù)責(zé)接收數(shù)據(jù)*/ thread=newThread(this); thread.start(); } /**實(shí)現(xiàn)監(jiān)聽(tīng)事件*/ publicvoidactionPerformed(ActionEvente){ if(e.getSource()==msg_send||e.getSource()==send){//外層if語(yǔ)句開(kāi)始 if(msg_send.getText()!=""){//內(nèi)層if開(kāi)始 //將要發(fā)送的數(shù)據(jù)字符串轉(zhuǎn)換為字節(jié)數(shù)組 bytebuffer[]=msg_send.getText().trim().getBytes(); try{ //獲取本機(jī)IP地址對(duì)象 InetAddressaddress=InetAddress.getByName("localhost"); //發(fā)送數(shù)據(jù)的數(shù)據(jù)包,其目標(biāo)端口是3441,接收方需在這個(gè)端口接收 //創(chuàng)建發(fā)送數(shù)據(jù)報(bào)的套接字 DatagramSocketmail_data=newDatagramSocket(); /**ParagramPacket對(duì)象方法調(diào)用*/ msg_show.append("數(shù)據(jù)報(bào)目標(biāo)主機(jī)地址:"+data_pack.getAddress()+"\n"); msg_show.append("數(shù)據(jù)報(bào)目標(biāo)端口是:"+data_pack.getPort()+"\n"); msg_show.append("數(shù)據(jù)報(bào)長(zhǎng)度:"+data_pack.getLength()+"\n"); msg_show.append("梁山伯說(shuō):"+msg_send.getText().trim()+"\n"); msg_send.getText(); mail_data.send(data_pack);//發(fā)送數(shù)據(jù)報(bào) }catch(Exceptionex){ } }//內(nèi)層if結(jié)束 }//外層if結(jié)束 }//方法定義結(jié)束 /**線程調(diào)用方法,負(fù)責(zé)數(shù)據(jù)接收*/ publicvoidrun(){ DatagramSocketmail_data=null;//接收數(shù)據(jù)包的套接字 bytedata[]=newbyte[8192];//存放接收數(shù)據(jù)的字節(jié)數(shù)組 DatagramPacketpack=null;//接收數(shù)據(jù)的數(shù)據(jù)報(bào)對(duì)象 try{ pack=newDatagramPacket(data,data.length); //使用端口3445來(lái)接收數(shù)據(jù)包(因?yàn)閷?duì)方發(fā)來(lái)的數(shù)據(jù)報(bào)的目標(biāo)端口是3445) mail_data=newDatagramSocket(3445); }catch(Exceptione){ } /**利用循環(huán)不斷接收數(shù)據(jù)*/ while(true){ if(mail_data==null) break; else try{ mail_data.receive(pack);//接收數(shù)據(jù)包 /**處理接收到的數(shù)據(jù), *獲取收到的數(shù)據(jù)的實(shí)際長(zhǎng)度, *獲取收到的數(shù)據(jù)包的始發(fā)地址, *獲取收到的數(shù)據(jù)包的始發(fā)端口。 */ intlength=pack.getLength(); InetAddressadress=pack.getAddress(); intport=pack.getPort(); Stringmessage=newString(pack.getData(),0,length); msg_show.append("收到數(shù)據(jù)長(zhǎng)度"+length+"\n"); msg_show.append("收到數(shù)據(jù)來(lái)自"+adress+"端口"+port+"\n"); //將接收到的數(shù)據(jù)顯示在信息顯示框中 msg_show.append("祝英臺(tái)說(shuō):"+message+"\n"); }catch(Exceptione){ } } }}/**UDP_YOU端代碼:UDP_YOU.java**/packageudp;//類(lèi)包import.*;importjava.io.*;importjava.awt.*;importjava.awt.event.*;importjavax.swing.*;importjavax.swing.event.*; publicclassUDP_YOUextendsJFrame{ publicUDP_YOU(){ Chat_youcs=newChat_you(); getContentPane().add(cs); } publicstaticvoidmain(String[]args){ UDP_YOUframe=newUDP_YOU(); frame.setTitle("祝英臺(tái)界面"); frame.setSize(510,500); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }}classChat_youextendsJPanelimplementsRunnable,ActionListener{ JButtonsend;//發(fā)送按鈕 TextAreamsg_show;//信息顯示框 TextFieldmsg_send;//信息發(fā)送框 Threadthread=null;//負(fù)責(zé)接收數(shù)據(jù)的線程 /**下面初始化界面*/ publicChat_you(){ setLayout(null); send=newJButton("發(fā)送"); msg_show=newTextArea(); msg_send=newTextField(); JLabeljl=newJLabel("信息顯示區(qū)"); jl.setBounds(0,0,500,20); add(jl); /**添加信息顯示框到面板上*/ msg_show.setBounds(0,20,500,300); msg_show.setEditable(false); add(msg_show); JLabeljl1=newJLabel("信息發(fā)送區(qū)"); jl1.setBounds(0,320,500,20); add(jl1); /**添加信息發(fā)送框到面板上*/ msg_send.setBounds(0,340,400,80); add(msg_send); msg_send.addActionListener(this);//為信息發(fā)送框設(shè)置監(jiān)聽(tīng)器 /**添加發(fā)送按鈕到面板上*/ send.setBounds(400,360,100,40); add(send); send.addActionListener(this);//為發(fā)送按鈕設(shè)置監(jiān)聽(tīng)器 /**建立并啟動(dòng)線程,負(fù)責(zé)接收數(shù)據(jù)*/ thread=newThread(this); thread.start(); } /**實(shí)現(xiàn)監(jiān)聽(tīng)事件*/ publicvoidactionPerformed(ActionEvente){ if(e.getSource()==msg_send||e.getSource()==send){ if(msg_send.getText()!=""){ //將要發(fā)送的數(shù)據(jù)字符串轉(zhuǎn)換為字節(jié)數(shù)組 bytebuffer[]=msg_send.getText().trim().getBytes(); try{ //獲取本機(jī)IP地址對(duì)象 InetAddressaddress=InetAddress.getByName("localhost"); //發(fā)送數(shù)據(jù)的數(shù)據(jù)包,其目標(biāo)端口是3445,接收方需在這個(gè)端口接收 DatagramPacketdata_pack=newDatagramPacket(buffer, buffer.length,address,3445); //創(chuàng)建發(fā)送數(shù)據(jù)報(bào)的套接字 DatagramSocketmail_data=newDatagramSocket(); /**ParagramPacket對(duì)象方法調(diào)用*/ msg_show.append("數(shù)據(jù)報(bào)目標(biāo)主機(jī)地址:"+data_pack.getAddress()+"\n"); msg_show.append("數(shù)據(jù)報(bào)目標(biāo)端口是:"+data_pack.getPort()+"\n"); msg_show.append("數(shù)據(jù)報(bào)長(zhǎng)度:"+data_pack.getLength()+"\n"); msg_show.append("祝英臺(tái)說(shuō):"+msg_send.getText().trim()+"\n"); msg_send.setText(null); mail_data.send(data_pack);//發(fā)送數(shù)據(jù)報(bào) }catch(Exceptionex){ } } } } /**線程調(diào)用方法,負(fù)責(zé)數(shù)據(jù)接收*/ publicvoidrun(){ DatagramSocketmail_data=null;//接收數(shù)據(jù)包的套接字 bytedata[]=newbyte[8192];//存放接收數(shù)據(jù)的字節(jié)數(shù)組 DatagramPacketpack=null;//接收數(shù)據(jù)的數(shù)據(jù)報(bào)對(duì)象 try{ pack=newDatagramPacket(data,data.length); //使用端口3441來(lái)接收數(shù)據(jù)包(因?yàn)閷?duì)方發(fā)來(lái)的數(shù)據(jù)報(bào)的目標(biāo)端口是3441) mail_data=newDatagramSocket(3441); }catch(Exceptione){ } /**利用循環(huán)不斷接收數(shù)據(jù)*/ while(true){ if(mail_data==null) break; else try{ mail_data.receive(pack);//接收數(shù)據(jù)包 /**處理接收到的信息, *獲取收到的數(shù)據(jù)的實(shí)際長(zhǎng)度, *獲取收到的數(shù)據(jù)包的始發(fā)地址, *獲取收到的數(shù)據(jù)包的始發(fā)端口, *將數(shù)據(jù)轉(zhuǎn)換為字符串。 */ intlength=pack.getLength(); InetAddressadress=pack.getAddress(); intport=pack.getPort(); Stringmessage=newString(pack.getData(),0,length); msg_show.append("收到數(shù)據(jù)長(zhǎng)度"+length+"\n"); msg_show.append("收到數(shù)據(jù)來(lái)自"+adress+"端口"+port+"\n"); //將接收到的數(shù)據(jù)顯示在信息顯示框中 msg_show.append("梁山伯說(shuō):"+message+"\n"); }catch(Exceptione){ msg_show.append("對(duì)方已斷開(kāi)連接"); } } }}將上面兩個(gè)程序放在UDP目錄下編譯,然后,執(zhí)行服務(wù)器和客戶(hù)程序。14.5廣播數(shù)據(jù)報(bào)14.5.1廣播數(shù)據(jù)報(bào)概要廣播數(shù)據(jù)報(bào)類(lèi)似于電臺(tái)廣播。進(jìn)行廣播的電臺(tái)需在指定的波段和頻率上廣播信息,接收者只有將收音機(jī)調(diào)到指定的波段、頻率上才能收聽(tīng)到廣播的內(nèi)容。廣播數(shù)據(jù)報(bào)涉及到地址和端口。Internet的地址是以a.b.c.d的格式給出,該地址的一部分代表用戶(hù)自己的主機(jī),而另一部分代表用戶(hù)所在的網(wǎng)絡(luò)。當(dāng)a小于128,那么b.c.d就用來(lái)表示主機(jī),這類(lèi)地址稱(chēng)為A類(lèi)地址;如果a大于等于128并且小于192,則a.b表示網(wǎng)絡(luò)地址,而c.d表示主機(jī)地址,這類(lèi)地址稱(chēng)為B類(lèi)地址;如果a大于或等于192,小于224則網(wǎng)絡(luò)地址是a.b.c。而d表示主機(jī)地址,這類(lèi)地址稱(chēng)為C類(lèi)地址;與55是保留地址,稱(chēng)為D類(lèi)地址。廣播或接收廣播的主機(jī)都必須加入到同一個(gè)D類(lèi)地址。一個(gè)D類(lèi)地址也稱(chēng)為一個(gè)廣播組。加入到同一個(gè)廣播組的主機(jī)可以在某個(gè)端口上廣播信息,也可以在某個(gè)端口號(hào)上接收信息。14.5.2MultiCastSocket類(lèi)多播數(shù)據(jù)報(bào)套接字用于發(fā)送和接收IP多播數(shù)據(jù)包。MulticastSocket是一種(UDP)DatagramSocket。它具有加入Internet上其他多播主機(jī)所屬“組”的功能(多播組通過(guò)D類(lèi)IP地址和標(biāo)準(zhǔn)UDP端口號(hào)指定)。D類(lèi)IP地址的范圍是~55(包括兩者)。地址被保留(不許使用)。首先使用所需端口創(chuàng)建MulticastSocket對(duì)象,然后調(diào)用joinGroup(InetAddressgroupAddr)方法來(lái)加入多播組。1.MulticastSocket的構(gòu)造方法(1)MulticastSocket():創(chuàng)建多播套接字。(2)MulticastSocket(intport):創(chuàng)建多播套接字,并將其綁定到特定端口。(3)MulticastSocket(SocketAddressbindaddr):創(chuàng)建綁定到指定套接字地址的MulticastSocket對(duì)象。這3個(gè)構(gòu)造方法都會(huì)拋出IOException異?;騍ecurityException異常,所以必須在try-catch結(jié)構(gòu)中創(chuàng)建MulticastSocket對(duì)象。2.MulticastSocket的實(shí)用方法publici
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度戶(hù)外活動(dòng)演出委托合同示范文本3篇
- 二零二五年度教育培訓(xùn)分公司注冊(cè)與課程開(kāi)發(fā)合同3篇
- 水下沉井施工方案
- 二零二五年度城市更新改造個(gè)人工程勞務(wù)分包服務(wù)協(xié)議
- 2025版水塔拆除工程中涉及地下管線保護(hù)的承包合同3篇
- 二零二五年度冷鏈物流蔬菜批發(fā)市場(chǎng)供銷(xiāo)合同3篇
- 二零二五版消防工程維保與消防設(shè)施升級(jí)改造合同3篇
- 個(gè)體工商戶(hù)的勞動(dòng)合同范本
- 能源項(xiàng)目投資建設(shè)及運(yùn)營(yíng)協(xié)議
- 二零二五版商業(yè)街區(qū)物業(yè)招商中介服務(wù)合同范本3篇
- 危險(xiǎn)品倉(cāng)儲(chǔ)危險(xiǎn)廢物處置與管理考核試卷
- 2024版汽車(chē)融資擔(dān)保合同范本版B版
- 浙江寧波鎮(zhèn)海區(qū)2025屆中考生物對(duì)點(diǎn)突破模擬試卷含解析
- 湖南省長(zhǎng)沙市2025年新高考適應(yīng)性考試生物學(xué)模擬試題(含答案)
- 工業(yè)自動(dòng)化設(shè)備維護(hù)保養(yǎng)方案
- 《中醫(yī)心理學(xué)》課件
- 心肌梗死病人護(hù)理課件
- 宮頸癌中醫(yī)護(hù)理查房
- 《費(fèi)曼學(xué)習(xí)法》讀后感
- 2023年安徽省公務(wù)員錄用考試《行測(cè)》真題及答案解析
- 《阻燃材料與技術(shù)》課件 顏龍 第3、4講 阻燃基本理論、阻燃劑性能與應(yīng)用
評(píng)論
0/150
提交評(píng)論