版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
精選優(yōu)質(zhì)文檔-----傾情為你奉上精選優(yōu)質(zhì)文檔-----傾情為你奉上專心---專注---專業(yè)專心---專注---專業(yè)精選優(yōu)質(zhì)文檔-----傾情為你奉上專心---專注---專業(yè)一、設(shè)計(jì)思想本課程設(shè)計(jì)主要是基于UDP的并用Java實(shí)現(xiàn)的簡單的聊天程序。UDP
用戶數(shù)據(jù)報(bào)是在運(yùn)輸層的端到端抽象的邏輯信道中傳送的。UDP
在傳送數(shù)據(jù)之前不需要先建立連接。對(duì)方的運(yùn)輸層在收到
UDP
報(bào)文后,不需要給出任何確認(rèn)。雖然
UDP
不提供可靠交付,但在某些情況下
UDP
是一種最有效的工作方式。雖然UDP
用戶數(shù)據(jù)報(bào)只能提供不可靠的交付,但
UDP
在某些方面有其特殊的優(yōu)點(diǎn),它有即時(shí)通信的功能。比如說,使用聊天程序聊天的時(shí)候,省去的了跟對(duì)方通信的時(shí)候的鏈接的麻煩,直接進(jìn)行通信。UDP
只在
IP
的數(shù)據(jù)報(bào)服務(wù)之上增加了很少一點(diǎn)的功能,即端口的功能和差錯(cuò)檢測(cè)的功能。UDP
使用盡最大努力交付,即不保證可靠交付,同時(shí)也不使用擁塞控制。UDP
是面向報(bào)文的。UDP
沒有擁塞控制,很適合多媒體通信的要求。UDP
支持一對(duì)一、一對(duì)多、多對(duì)一和多對(duì)多的交互通信。發(fā)送方
UDP
對(duì)應(yīng)用程序交下來的報(bào)文,在添加首部后就向下交付
IP
層。UDP
對(duì)應(yīng)用層交下來的報(bào)文,既不合并,也不拆分,而是保留這些報(bào)文的邊界。應(yīng)用層交給
UDP
多長的報(bào)文,UDP
就照樣發(fā)送,即一次發(fā)送一個(gè)報(bào)文。接收方
UDP
對(duì)
IP
層交上來的
UDP
用戶數(shù)據(jù)報(bào),在去除首部后就原封不動(dòng)地交付上層的應(yīng)用進(jìn)程,一次交付一個(gè)完整的報(bào)文。Socket又稱作套接字,它是使用標(biāo)準(zhǔn)Unix文件描述符(filedescriptor)和其它程序通訊的方式。使用send()和recv()讓你更好的控制數(shù)據(jù)傳輸。在Java網(wǎng)絡(luò)編程中,socket相當(dāng)于應(yīng)用程序的港口碼頭;在計(jì)算機(jī)網(wǎng)絡(luò)中,套接字由ip地址和端口號(hào)組成,為進(jìn)程之間通信提供地址。兩個(gè)主機(jī)進(jìn)行通信實(shí)際上就是兩個(gè)主機(jī)中的應(yīng)用進(jìn)程互相通信,應(yīng)用進(jìn)程之間的通信又稱為端到端的通信。為應(yīng)用進(jìn)程之間的通信提供運(yùn)輸服務(wù)的是運(yùn)輸層的運(yùn)輸協(xié)議,運(yùn)輸層需要有兩種不同的運(yùn)輸協(xié)議,即面向連接的TCP和無連接的UDP。在Java中,用于實(shí)現(xiàn)基于UDP的聊天程序,使用兩個(gè)重要的類(DatagramSocket類和DatagramPacket類)。DatagramSocket類表示用來發(fā)送和接收數(shù)據(jù)報(bào)包的套接字。數(shù)據(jù)報(bào)套接字是包投遞服務(wù)的發(fā)送或接收點(diǎn)。每個(gè)在數(shù)據(jù)報(bào)套接字上發(fā)送或接收的包都是單獨(dú)編址和路由的。從一臺(tái)機(jī)器發(fā)送到另一臺(tái)機(jī)器的多個(gè)包可能選擇不同的路由,也可能按不同的順序到達(dá)。在DatagramSocket上總是啟用UDP廣播發(fā)送。為了接收廣播包,應(yīng)該將DatagramSocket綁定到通配符地址。在某些實(shí)現(xiàn)中,將DatagramSocket綁定到一個(gè)更加具體的地址時(shí)廣播包也可以被接收。DatagramPacket類表示數(shù)據(jù)報(bào)包。數(shù)據(jù)報(bào)包用來實(shí)現(xiàn)無連接包投遞服務(wù)。每條報(bào)文僅根據(jù)該包中包含的信息從一臺(tái)機(jī)器路由到另一臺(tái)機(jī)器。從一臺(tái)機(jī)器發(fā)送到另一臺(tái)機(jī)器的多個(gè)包可能選擇不同的路由,也可能按不同的順序到達(dá)。不對(duì)包投遞做出保證。服務(wù)程序工作在服務(wù)器的某個(gè)端口上,一旦啟動(dòng)服務(wù),它將在這個(gè)端口上監(jiān)聽,等待客戶程序發(fā)來請(qǐng)求,當(dāng)有客戶連接到該端口,accept()方法就返回一個(gè)Socket對(duì)象,可以用該對(duì)象獲得一個(gè)輸入輸出流。服務(wù)器的套接字用服務(wù)器套接字類(ServerSocket)來建立。具體實(shí)現(xiàn)如下:建立一個(gè)服務(wù)者,端口為5000。(2)服務(wù)者永遠(yuǎn)等待,一旦客戶送來正確的請(qǐng)求,連接至該端口,accept()方法就返回一個(gè)Socket對(duì)象。(3)用返回的Socket對(duì)象創(chuàng)建數(shù)據(jù)輸入流類的實(shí)例in。用返回的Socket對(duì)象創(chuàng)建數(shù)據(jù)輸出流的實(shí)例out。以上實(shí)例in和out是服務(wù)者用于從客戶接受輸入信息和向客戶程序發(fā)送信息所用。此外,還需要用方法readline()和println()讀取或輸出一行數(shù)據(jù)。(4)soc.close()關(guān)閉Socket。算法流程圖本程序的核心算法流程圖如下圖所示:用戶1用戶1封裝數(shù)據(jù)報(bào)解析數(shù)據(jù)報(bào)目的IP與主機(jī)IP比較接受消息用戶2是否傳輸數(shù)據(jù)報(bào)丟棄發(fā)送數(shù)據(jù)報(bào)圖1程序算法流程圖三、源代碼importjava.awt.AWTEvent;importjava.awt.Color;importjava.awt.Dimension;importjava.awt.Rectangle;importjava.awt.TextArea;importjava.awt.Toolkit;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.WindowEvent;importjava.io.IOException;.DatagramPacket;.DatagramSocket;.InetAddress;.SocketException;importjavax.swing.JButton;importjavax.swing.JCheckBox;importjavax.swing.JFrame;importjavax.swing.JLabel;importjavax.swing.JOptionPane;importjavax.swing.JPanel;importjavax.swing.JTextField;@SuppressWarnings("serial")publicclassUDPextendsJFrame{ //創(chuàng)建主界面 staticJPanelmainPane; //創(chuàng)建“發(fā)送信息”標(biāo)簽 JLabelsendMSGLabel=newJLabel("發(fā)送信息:"); //創(chuàng)建“輸入對(duì)方ip地址”標(biāo)簽 JLabelipAddressLabel=newJLabel(); //創(chuàng)建“群聊”標(biāo)簽 JLabelqunLabel=newJLabel("群聊"); //創(chuàng)建發(fā)送文本框 JTextFieldsendMSGText=newJTextField(); //創(chuàng)建ip文本框 JTextFieldipAddressText=newJTextField(); //創(chuàng)建“發(fā)送”按鈕 JButtonsendMSGButton=newJButton("發(fā)送"); //創(chuàng)建“群聊”選擇框 JCheckBoxqunCB=newJCheckBox(); //創(chuàng)建聊天信息文本框 staticTextAreaMSGText=newTextArea(); //輸入端口 intIn=3001; //輸出端口 intOut=3000; //聲明發(fā)送和接收數(shù)據(jù)包引用 staticDatagramPacketsendDP,getDP; //聲明發(fā)送和接收套接字引用 staticDatagramSocketsendDS,getDS; //界面開關(guān) staticbooleanpackFrame=false; //群聊開關(guān) staticbooleanisQun=false; //程序主方法 publicstaticvoidmain(String[]args){ //創(chuàng)建UDP類實(shí)例 UDPframe=newUDP(); //判定主界面是否以創(chuàng)建 if(packFrame){ frame.pack(); }else{ frame.validate(); } //放置窗體在屏幕中央 DimensionscreenSize=Toolkit.getDefaultToolkit().getScreenSize(); DimensionframeSize=frame.getSize(); if(frameSize.height>screenSize.height){ frameSize.height=screenSize.height; } if(frameSize.width>screenSize.width){ frameSize.width=screenSize.width; } frame.setLocation((screenSize.width-frameSize.width)/2, (screenSize.height-frameSize.height)/2); frame.setVisible(true); //接受局域網(wǎng)消息 while(true){ try{ //創(chuàng)建接受字符串 Stringreceived=null; //創(chuàng)建接受數(shù)組 byte[]array=newbyte[100]; //創(chuàng)建接受數(shù)據(jù)包 getDP=newDatagramPacket(array,array.length); //創(chuàng)建接受套接字 getDS.receive(getDP); //判定消息是否為群發(fā) if(!getDP .getAddress() .toString() .equals("/"+InetAddress.getLocalHost().getHostAddress() .toString())){ //如果為私聊,則顯示以下消息 MSGText.append("\n"+getDP.getAddress().toString().substring(1)+"說:"); received=newString(getDP.getData(),0, getDP.getLength(),"UTF-8"); MSGText.append(received); } //捕獲異常 }catch(IOExceptionse){ se.printStackTrace(); } } } //重構(gòu)構(gòu)造方法 publicUDP(){ enableEvents(AWTEvent.WINDOW_EVENT_MASK); try{ //構(gòu)建主窗體 mainPane=(JPanel)this.getContentPane(); //設(shè)置主窗體的布局 mainPane.setLayout(null); //設(shè)置主窗體的大小 this.setSize(newDimension(363,500)); //設(shè)置標(biāo)題 this.setTitle("基于UDP的局域網(wǎng)聊天室"); //設(shè)置ip輸入框的文字為“輸入對(duì)方IP地址” ipAddressLabel.setText("輸入對(duì)方IP地址:"); //設(shè)置ip地址標(biāo)簽的位置 ipAddressLabel.setBounds(newRectangle(12,20,109,23)); //設(shè)置ip地址輸入框的位置 ipAddressText.setBounds(newRectangle(123,20,120,19)); //設(shè)置群聊標(biāo)簽的位置 qunLabel.setBounds(270,20,40,20); //設(shè)置群聊選擇框的位置 qunCB.setBounds(295,20,20,20); //為群聊選擇框添加監(jiān)聽器 qunCB.addActionListener(newActionListener(){ //重寫處理方法 @Override publicvoidactionPerformed(ActionEvente){ //將群聊選擇框反選 isQun=!isQun; //設(shè)置ip地址輸入框?yàn)椴豢捎? ipAddressText.setEditable(!isQun); } }); //設(shè)置聊天記錄框的位置 MSGText.setBounds(newRectangle(11,60,333,355)); //設(shè)置聊天記錄框?yàn)榭捎? MSGText.setEditable(false); //設(shè)置聊天記錄框背景色為白色 MSGText.setBackground(Color.white); //設(shè)置發(fā)送消息標(biāo)簽的位置 sendMSGLabel.setBounds(newRectangle(13,430,65,20)); //設(shè)置發(fā)送文本框的位置 sendMSGText.setBounds(newRectangle(80,430,190,20)); //設(shè)置發(fā)送按鈕的位置 sendMSGButton.setBounds(newRectangle(280,430,65,20)); //添加發(fā)送按鈕的監(jiān)聽器 sendMSGButton .addActionListener(newjava.awt.event.ActionListener(){ //重寫處理方法 publicvoidactionPerformed(ActionEvente){ try{ //判定是否為群聊消息 if(isQun){ //如果是群聊,則顯示以下消息 MSGText.append("\n您對(duì)大家說:" +sendMSGText.getText()); //創(chuàng)建比特?cái)?shù)組 bytedata[]=sendMSGText.getText() .getBytes("UTF-8"); //創(chuàng)建數(shù)據(jù)包 sendDP=newDatagramPacket( //數(shù)據(jù) data, //數(shù)據(jù)長度 data.length, //ip地址 InetAddress .getByName("55"), //輸出端口 In); //發(fā)送數(shù)據(jù)包 sendDS.send(sendDP); }else{ //如果是私聊,則顯示以下消息 MSGText.append("\n您對(duì)" +ipAddressText.getText()+"說:" +sendMSGText.getText()); //創(chuàng)建比特?cái)?shù)組 bytedata[]=sendMSGText.getText() .getBytes("UTF-8"); //創(chuàng)建數(shù)據(jù)包 sendDP=newDatagramPacket( //數(shù)據(jù) data, //數(shù)據(jù)長度 data.length, //ip地址 InetAddress.getByName(ipAddressText .getText()), //輸出端口 In); //發(fā)送數(shù)據(jù)包 sendDS.send(sendDP); } //捕獲異常 }catch(IOExceptionexc){ System.out.println("您不在局域網(wǎng)!"); } //清空發(fā)送消息文本框內(nèi)容 sendMSGText.setText(""); } }); //把ip地址標(biāo)簽添加進(jìn)主界面 mainPane.add(ipAddressLabel,null); //把發(fā)送消息標(biāo)簽添加進(jìn)主界面 mainPane.add(sendMSGLabel,null); //把發(fā)送消息文本框添加進(jìn)主界面 mainPane.add(sendMSGText,null); //把ip地址輸入框添加進(jìn)主界面 mainPane.add(ipAddressText,null); //把消息記錄框添加進(jìn)主界面 mainPane.add(MSGText,null); //把發(fā)送按鈕添加進(jìn)主界面 mainPane.add(sendMSGButton,null); //把群聊標(biāo)簽添加進(jìn)主界面 mainPane.add(qunLabel,null); //把群聊選擇框添加進(jìn)主界面 mainPane.add(qunCB); //設(shè)置各組件為可見 this.setVisible(true); try{ //創(chuàng)建發(fā)送端口套接字 sendDS=newDatagramSocket(Out); //創(chuàng)建接受端口套接字 getDS=newDatagramSocket(In); //異常捕獲 }catch(SocketExceptionse){ se.printStackTrace(); //捕獲異常后退出系統(tǒng) System.exit(0); } //捕獲異常 }catch(Exceptione){ e.printStackTrace(); } } //重載關(guān)閉按鈕函數(shù) protectedvoidprocessWindowEvent(WindowEvente){ cessWindowEvent(e); if(e.getID()==WindowEvent.WINDOW_CLOSING){ System.exit(0); } }}運(yùn)行結(jié)果軟件運(yùn)行出事界面如下:圖2軟件初始界面之后輸入對(duì)方ip地址,在下面的輸入框內(nèi)輸入想要說的文字:圖3輸入ip地址點(diǎn)擊“發(fā)送”按鈕,發(fā)送消息:圖4點(diǎn)擊“發(fā)送”按鈕接收到對(duì)方的信息:圖5收到對(duì)方私聊信息勾選群聊選項(xiàng),輸入想說的話:圖6發(fā)送群聊信息收到其他人的群聊信息:圖7收到群聊信息五、遇到的問題及解決這部分我主要遇到了如下兩個(gè)問題,其內(nèi)容與解決方法如下所列:1.程序無法發(fā)送和接收數(shù)據(jù)解決方法:沒有弄明白DatagramPacket和DatagramSocket的用法和區(qū)別。DatagramPacket和DatagramSocket都存在中。DatagramPacket表示存放數(shù)據(jù)的數(shù)據(jù)報(bào),DatagramSocket表示接受或發(fā)送數(shù)據(jù)報(bào)的套接字。DatagramPacket實(shí)例,并將其作為參數(shù)傳遞給DatagramSocket類的send()方法。接收信息時(shí),Java程序首先創(chuàng)建一個(gè)DatagramPacket實(shí)例,該實(shí)例中預(yù)先分配了一些空間(一個(gè)字節(jié)數(shù)組byte[]),并將接收到的信息存放在該空間中。然后把該實(shí)例作為參數(shù)傳遞給DatagramSocket類的receive()方法。除傳輸?shù)男畔⒈旧硗?,每個(gè)DatagramPacket實(shí)例中還附加了地址和端口信息,其具體含義取決于該數(shù)據(jù)報(bào)文是被發(fā)送還是被接收。若是要發(fā)送的數(shù)據(jù)報(bào)文,DatagramPacket實(shí)例中的地址則指明了目的地址和端口號(hào),若是接收到的數(shù)據(jù)報(bào)文,DatagramPacket實(shí)例中的地址則指明了所收信息的源地址。因此,服務(wù)器端可以修改接收到的DatagramPacket實(shí)例的緩存區(qū)內(nèi)容,再將這個(gè)實(shí)例連同修改后的信息一起,發(fā)回給它的源地址。Java使用DatagramSocket代表UDP協(xié)議的Socket,DatagramSocket本身只是碼頭,不維護(hù)狀態(tài),不能產(chǎn)生IO流,它的唯一作用就是接收和發(fā)送數(shù)據(jù)報(bào),Java使用DatagramPacket來代表數(shù)據(jù)報(bào),DatagramSocket接收和發(fā)送的數(shù)據(jù)都是通過DatagramPacket對(duì)象完成的。2.在程序中加入圖片,用代碼讀取圖片路徑設(shè)置為絕對(duì)路徑,導(dǎo)致程序移動(dòng)之后,圖片文件無法被讀取。解決辦法:從網(wǎng)上搜索資料,參考大神博客,真正理解什么是絕對(duì)路徑和相對(duì)路徑的區(qū)別以及在項(xiàng)目開發(fā)中用法的不同。所謂的絕對(duì)路徑,就是文件在整個(gè)文件系統(tǒng)的全路徑,如在Windows下,D:\JAVA\MyEclipse\MyEclipse10這個(gè)文件夾或者D:\JAVA\MyEclipse\MyEclipse10\myeclipse.exe這個(gè)文件,都是以全路徑名的形式出現(xiàn)的。只是在Java代碼中,\是必須轉(zhuǎn)義的,所以我們寫絕對(duì)路徑時(shí),總會(huì)D:\\JAVA\MyEclipse\\MyEclipse10\\myeclipse.exe。如代碼中:Filefile04=newFile("C:\\test1\\test101\\SeProjectFileDemo04.txt");Filefile05=newFile(dirAbsPath05,"SeProjectFileDemo05.txt");這兩種都是絕對(duì)路徑的寫法,其中前者中C:\\test1\\test101\\的目錄必須事先已經(jīng)存在者兩個(gè)目錄,后者dirAbsPath05也必須是已經(jīng)創(chuàng)建好的目錄,如代碼中就Filedir05=newFile("C:\\test2\\test201");if(!dir05.exists())dir05.mkdirs();所謂的相對(duì)路徑,就是相對(duì)某個(gè)目錄的情況下,某個(gè)資源文件的短名稱,這其中就涉及到參考誰的問題了。如:如果我說,以后你們寫相對(duì)路徑,都是以D:\\JAVA\MyEclipse\\MyEclipse10這個(gè)目錄為參考點(diǎn),那么Filefile=newFile("myeclipse.exe");中的"myeclipse.exe"就是一個(gè)相對(duì)路徑的寫法。六、心得體會(huì)這次的課程設(shè)計(jì),我覺得還是很成功的。先是成功實(shí)現(xiàn)了此次設(shè)計(jì)的要求,另外我還添加了群聊功能。一開始并不打算選這個(gè)題目的時(shí)候,后來只是抱著試試看的心理,這部分的知識(shí)應(yīng)該說是沒有學(xué)過,老師上課也沒有講這個(gè)SOCKET套接字的部分,是要我們課后自己看的。我只好把書上的一段基于客戶-服務(wù)器端的計(jì)算三角形面積的java代碼先調(diào)試一下,熟悉一下代碼運(yùn)行的效果,給我一點(diǎn)思路。再根據(jù)這個(gè)程序的框架,來編寫代碼,但是后來發(fā)現(xiàn)自己編代碼并不簡單,折騰了好久也沒成功,覺得自己的設(shè)計(jì)思路有點(diǎn)偏差,所以才導(dǎo)致這個(gè)程序的失敗,看來把理論變成實(shí)踐可真不是一件簡簡單單就能完成的事。
接下來的幾
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度大數(shù)據(jù)中心運(yùn)營維護(hù)合同
- 2024年建筑工程設(shè)計(jì)與咨詢合同
- 2024年度航空公司機(jī)票代理合同
- 2024年度環(huán)保工程與技術(shù)咨詢合同
- 幼兒食品課件教學(xué)課件
- 美術(shù)課件價(jià)格教學(xué)課件
- 尿道異物課件教學(xué)課件
- 2024年塑料纖維生產(chǎn)加工許可合同
- 2024年建筑人才中介服務(wù)協(xié)議
- 2024年度南京市存量房購買合同
- 供電線路維護(hù)合同
- 胸部術(shù)后護(hù)理科普
- 鞋子工廠供貨合同模板
- 2024碼頭租賃合同范本
- 木材采運(yùn)智能決策支持系統(tǒng)
- 【產(chǎn)業(yè)圖譜】2024年青島市重點(diǎn)產(chǎn)業(yè)規(guī)劃布局全景圖譜(附各地區(qū)重點(diǎn)產(chǎn)業(yè)、產(chǎn)業(yè)體系布局、未來產(chǎn)業(yè)發(fā)展規(guī)劃等)
- 上海市市轄區(qū)(2024年-2025年小學(xué)四年級(jí)語文)部編版期末考試(下學(xué)期)試卷及答案
- 認(rèn)識(shí)梯形(課件)四年級(jí)上冊(cè)人教版
- 【期中考后反思】《反躬自省,砥礪奮進(jìn)》-2022-2023學(xué)年初中主題班會(huì)課件
- 2019新教材人教版生物必修1教材課后習(xí)題答案
- 2024年中國白酒行業(yè)數(shù)字化轉(zhuǎn)型研究報(bào)告-36氪-202409
評(píng)論
0/150
提交評(píng)論