基于UDP協(xié)議網(wǎng)上聊天程序_第1頁
基于UDP協(xié)議網(wǎng)上聊天程序_第2頁
基于UDP協(xié)議網(wǎng)上聊天程序_第3頁
基于UDP協(xié)議網(wǎng)上聊天程序_第4頁
基于UDP協(xié)議網(wǎng)上聊天程序_第5頁
已閱讀5頁,還剩13頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、計算機(jī)網(wǎng)絡(luò)課程設(shè)計說明書題 目: 基于UDP協(xié)議網(wǎng)上聊天程序 學(xué) 院: 計算機(jī)科學(xué)與工程學(xué)院 專 業(yè): 信息安全 姓 名: 學(xué) 號: 1000360222 指導(dǎo)教師: 孫晉永 目錄1 協(xié)議介紹和使用說明31.1 協(xié)議內(nèi)容31.2 關(guān)鍵技術(shù)41.2.1 服務(wù)器端Socket的實現(xiàn)41.2.2 通信的建立52 程序設(shè)計62.1系統(tǒng)結(jié)構(gòu)62.2主程序設(shè)計72.2.1 服務(wù)器端程序72.2.2 客戶端程序72.3 各模塊設(shè)計8客戶端向服務(wù)器發(fā)送消息8客戶端之間發(fā)送消息82.4 界面設(shè)計82.4.1 聊天界面設(shè)計的方法82.4.2 界面的功能92.5 實現(xiàn)主要代碼92.6 程序調(diào)試及運行結(jié)果152.6.

2、1 調(diào)試前的準(zhǔn)備152.6.2 程序調(diào)試過程162.6.3 程序運行結(jié)果163 課設(shè)體會17參考文獻(xiàn)181 協(xié)議介紹和使用說明1.1 協(xié)議內(nèi)容本課程設(shè)計主要是基于UDP的并用Java實現(xiàn)的簡單的聊天程序。UDP 用戶數(shù)據(jù)報是在運輸層的端到端抽象的邏輯信道中傳送的。UDP 在傳送數(shù)據(jù)之前不需要先建立連接。對方的運輸層在收到 UDP 報文后,不需要給出任何確認(rèn)。雖然 UDP 不提供可靠交付,但在某些情況下 UDP 是一種最有效的工作方式。雖然UDP 用戶數(shù)據(jù)報只能提供不可靠的交付,但 UDP 在某些方面有其特殊的優(yōu)點,它有即時通信的功能。比如說,使用聊天程序聊天的時候,省去的了跟對方通信的時候的鏈

3、接的麻煩,直接進(jìn)行通信。UDP 只在 IP 的數(shù)據(jù)報服務(wù)之上增加了很少一點的功能,即端口的功能和差錯檢測的功能。UDP 使用盡最大努力交付,即不保證可靠交付,同時也不使用擁塞控制。UDP 是面向報文的。UDP 沒有擁塞控制,很適合多媒體通信的要求。UDP 支持一對一、一對多、多對一和多對多的交互通信。發(fā)送方 UDP 對應(yīng)用程序交下來的報文,在添加首部后就向下交付 IP 層。UDP 對應(yīng)用層交下來的報文,既不合并,也不拆分,而是保留這些報文的邊界。應(yīng)用層交給 UDP 多長的報文,UDP 就照樣發(fā)送,即一次發(fā)送一個報文。接收方 UDP 對 IP 層交上來的 UDP 用戶數(shù)據(jù)報,在去除首部后就原封不

4、動地交付上層的應(yīng)用進(jìn)程,一次交付一個完整的報文。 圖1.1UDP基本工作過程1.2 關(guān)鍵技術(shù) 服務(wù)器端Socket的實現(xiàn)Socket又稱作套接字,它是使用 標(biāo)準(zhǔn)Unix 文件描述符 (file descriptor) 和其它程序通訊的方式。使用send()和recv()讓你更好的控制數(shù)據(jù)傳輸。在Java 網(wǎng)絡(luò)編程中,socket相當(dāng)于應(yīng)用程序的港口碼頭;在計算機(jī)網(wǎng)絡(luò)中,套接字由ip地址和端口號組成,為進(jìn)程之間通信提供地址。兩個主機(jī)進(jìn)行通信實際上就是兩個主機(jī)中的應(yīng)用進(jìn)程互相通信,應(yīng)用進(jìn)程之間的通信又稱為端到端的通信。為應(yīng)用進(jìn)程之間的通信提供運輸服

5、務(wù)的是運輸層的運輸協(xié)議,運輸層需要有兩種不同的運輸協(xié)議,即面向連接的TCP和無連接的UDP。 在Java中,用于實現(xiàn)基于UDP的聊天程序,使用兩個重要的類(DatagramSocket類和DatagramPacket類)。DatagramSocket類表示用來發(fā)送和接收數(shù)據(jù)報包的套接字。數(shù)據(jù)報套接字是包投遞服務(wù)的發(fā)送或接收點。每個在數(shù)據(jù)報套接字上發(fā)送或接收的包都是單獨編址和路由的。從一臺機(jī)器發(fā)送到另一臺機(jī)器的多個包可能選擇不同的路由,也可能按不同的順序到達(dá)。 在DatagramSocket上總是啟用UDP廣播發(fā)送。為了接收廣播包,應(yīng)該將 DatagramSocket綁定到通配符地址。在某些實現(xiàn)

6、中,將DatagramSocket綁定到一個更加具體的地址時廣播包也可以被接收。atagramPacket類表示數(shù)據(jù)報包。 數(shù)據(jù)報包用來實現(xiàn)無連接包投遞服務(wù)。每條報文僅根據(jù)該包中包含的信息從一臺機(jī)器路由到另一臺機(jī)器。從一臺機(jī)器發(fā)送到另一臺機(jī)器的多個包可能選擇不同的路由,也可能按不同的順序到達(dá)。不對包投遞做出保證。服務(wù)程序工作在服務(wù)器的某個端口上,一旦啟動服務(wù),它將在這個端口上監(jiān)聽,等待客戶程序發(fā)來請求,當(dāng)有客戶連接到該端口,accept()方法就返回一個Socket對象,可以用該對象獲得一個輸入輸出流。服務(wù)器的套接字用服務(wù)器套接字類(ServerSocket)來建立。具體實現(xiàn)如下:(1)建立一

7、個服務(wù)者,端口為5000。(2)服務(wù)者永遠(yuǎn)等待,一旦客戶送來正確的請求,連接至該端口,accept()方法就返回一個Socket對象。(3)用返回的Socket對象創(chuàng)建數(shù)據(jù)輸入流類的實例in。用返回的Socket對象創(chuàng)建數(shù)據(jù)輸出流的實例out。以上實例in和out是服務(wù)者用于從客戶接受輸入信息和向客戶程序發(fā)送信息所用。此外,還需要用方法readline()和println()讀取或輸出一行數(shù)據(jù)。(4)soc.close()關(guān)閉Socket。 圖1.2 基于UDP的SOCKET編程模型 通信的建立 在客戶端建立Socket對象,并進(jìn)行異常處理,主機(jī)名和端口號與連接的服務(wù)器名和提供該服務(wù)的服務(wù)程序

8、的監(jiān)聽端口必須一致。建立連接后用Socket類提供的getInputStream()和getOutputStream()方法取得輸入輸出流。在服務(wù)器端,獲得的輸入流是客戶端的輸出流,而Socket獲得的輸出流是發(fā)向客戶端的輸入流,在客戶端也是這樣。獲得socket的輸入輸出流之后,為了便于讀寫操作,需要在這兩個流對象基礎(chǔ)上建立易于操作的數(shù)據(jù)流DateInputStream, DataOutputStream。然后對輸入輸出流進(jìn)行讀寫操作。在通信結(jié)束時關(guān)閉socket,以斷開連接,釋放資源。先關(guān)閉對應(yīng)的輸入輸出流,再關(guān)閉socket本身。2 程序設(shè)計2.1系統(tǒng)結(jié)構(gòu)本系統(tǒng)采用一個服務(wù)器端和多個客戶

9、端的聊天方式來實現(xiàn)。結(jié)構(gòu)圖如下所示:圖2.1服務(wù)器-客戶端結(jié)構(gòu)圖2.2主程序設(shè)計 服務(wù)器端程序 服務(wù)器與客戶間通過套接口Socket連接。在java中使用套接口相當(dāng)簡單,Java API為處理套接口的通信提供了一個類.Socket.,使得編寫網(wǎng)絡(luò)應(yīng)用程序相對容易服務(wù)器采用多線程以滿足多用戶的請求,程序用vector向量數(shù)組存儲連接客戶變量,通過創(chuàng)建一個ServerSocket對象來監(jiān)聽來自客戶的連接請求,默認(rèn)端口為6666,然后無限循環(huán)調(diào)用accept()方法接受客戶程序的連接。 客戶端程序 客戶端是一個Java Applet程序,客戶通過Socket 建立與服務(wù)器的連接。圖2.2主程序流程圖

10、 2.3 各模塊設(shè)計客戶端向服務(wù)器發(fā)送消息 服務(wù)器與客戶都通過構(gòu)造DataInputStream, PrintStream來建立輸入輸出流,然后雙方通過該輸入輸出流來相互傳遞信息,一旦收到客戶方的連接請求,服務(wù)器accept()方法返回一個新建的Socket對象??蛻舳巳缓笙蚍?wù)器發(fā)送消息, 客戶端之間發(fā)送消息 客戶間發(fā)送信息通過UDP協(xié)議來實現(xiàn),用戶登錄時通過類DatagramPacket和DatagramSocket創(chuàng)建UDP包括其本地接受端口以及發(fā)送端口,默認(rèn)端口為new DatagramSocket()和nickNameField.getText(),通過向服務(wù)器發(fā)送消息,然后服務(wù)器廣

11、播消息,最好達(dá)到群聊的目的??蛻舳税l(fā)送消息(send(DatagramPacket)和接受消息(receive(DatagramPacket)。 2.4 界面設(shè)計2.4.1 聊天界面設(shè)計的方法在Frame布局容器中,添加一個顯示聊天的TextArea文本框(在上面),加入Panel面板,Panel面板中包括一個發(fā)送消息的TextField單行文本框,“聊天記錄”和“發(fā)送”兩個按鈕監(jiān)聽。 圖2.3聊天界面實現(xiàn)功能圖2.4.2 界面的功能 客戶端登陸界面 輸入服務(wù)器IP,接收端口,及用戶名。登陸服務(wù)器,與服務(wù)器建立連接,進(jìn)入聊天界面??蛻舳肆奶旖缑妫M(jìn)行聊天。并可查看聊天記錄。服務(wù)器界面,監(jiān)聽客戶

12、端連接狀況并可發(fā)送服務(wù)器消息。2.5 實現(xiàn)主要代碼客戶端代碼:package udp;import java.io.*;import java.awt.*;import java.awt.event.*;import .*;class Client implements ActionListener, Runnable private Frame frame,f1,f2;/聊天窗口和登陸窗口private Panel p1, p2,p3;private Button sendButton,b,c,d;private TextField serverIpField,sendField,recei

13、vePortField, nickNameField;private TextArea currentUserField;boolean isClient = false;private TextArea messageArea; /聊天記錄框private String serverIp;private int serverReceivePort = 6666; /服務(wù)器接收默認(rèn)端口private DatagramSocket receiveSocket = null, sendSocket = null;private DatagramPacket receivePacket = null

14、, sendPacket = null; /客戶端登陸界面public void inputIP()/聊天記錄界面public void input()/客戶端聊天界面public void launchFrame() /啟動客戶端,完成登錄public void start() try sendSocket = new DatagramSocket();/ 客戶機(jī)發(fā)送端口sendMessage(nickNameField.getText() + ":"+ receivePortField.getText() + ":");/名字和接收端口new Thr

15、ead(this).start(); catch (Exception e) messageArea.append(e + "n");/客戶端發(fā)送消息public void sendMessage(String str) try ByteArrayOutputStream out = new ByteArrayOutputStream();/捕獲內(nèi)存緩沖區(qū)的數(shù)據(jù),轉(zhuǎn)換成字節(jié)數(shù)組PrintStream pout = new PrintStream(out);/輸出字節(jié)pout.print(str);byte buf = out.toByteArray();sendPacket

16、 = new DatagramPacket(buf, buf.length, InetAddress.getByName(serverIp), serverReceivePort);/構(gòu)造數(shù)據(jù)報包sendSocket.send(sendPacket);/發(fā)送數(shù)據(jù)報包buf = null; catch (Exception e) e.printStackTrace();messageArea.append("消息:" + str + " 發(fā)送失敗,你還沒有登錄,或已經(jīng)掉線!n");/多線程,啟動接收信息public void run() receiveMe

17、ssage();/ 客戶機(jī)接收消息public void receiveMessage()try receiveSocket = new DatagramSocket(Integer.parseInt(receivePortField.getText();/ 客戶機(jī)接受端口while (true) byte buf = new byte200;receivePacket = new DatagramPacket(buf, buf.length);receiveSocket.receive(receivePacket);if (receivePacket.getLength() = 0) mes

18、sageArea.append("空消息" + "n");continue;ByteArrayInputStream bin = new ByteArrayInputStream(receivePacket.getData();/字節(jié)串變成輸入流BufferedReader read = new BufferedReader(new InputStreamReader(bin);/先把字節(jié)流轉(zhuǎn)換為字符流,然后放入緩沖區(qū)String str= read.readLine();messageArea.append(str);if(str.contains(&

19、quot;迎:/")messageArea.append("n");read.close();bin.close(); catch (Exception e) messageArea.append(e + "sendmessage errorn"); /事件響應(yīng)處理public void actionPerformed(ActionEvent e) /程序主入口 public static void main(String args) Client client = new Client(); / client.input(); client.

20、inputIP(); 服務(wù)端端代碼:package udp;import java.io.*;import java.awt.*;import java.awt.event.*;import .*;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.Iterator;public class Server implements ActionListener private Frame frame; / 主窗體private Label connectLabel, mess

21、ageLabel;private TextArea messageArea; / 消息框,顯示用戶登錄信息private TextField sendField; / 輸入聊天內(nèi)容的文本框private Button sendButton; / 發(fā)送按鈕private DatagramSocket receiveSocket = null, sendSocket = null;private DatagramPacket receivePacket = null, sendPacket = null;private int serverReceivePort = 6666; / 服務(wù)器端的接收

22、端口private List<ClientMessage> clientList = new ArrayList<ClientMessage>(); / 保存連接的客戶端信息boolean isServer = true;/ 程序主入口public static void main(String args) Server server = new Server();server.launchFrame();server.start(); / 啟動服務(wù)器server.receiveMessage(); / 接收信息/ 服務(wù)端界面初始化public void launchF

23、rame() / 事件監(jiān)聽處理public void actionPerformed(ActionEvent e) / 啟動服務(wù)器public void start() try sendSocket = new DatagramSocket(6660);/ 服務(wù)器發(fā)送端口 catch (Exception e) messageArea.append(e + "n");/ 服務(wù)器接收消息public void receiveMessage()try receiveSocket = new DatagramSocket(serverReceivePort);/ 服務(wù)器接受端口w

24、hile (true) byte buf = new byte200;receivePacket = new DatagramPacket(buf, buf.length);receiveSocket.receive(receivePacket);int length = clientList.size();boolean have = false;ByteArrayInputStream bin = new ByteArrayInputStream(receivePacket.getData();BufferedReader read = new BufferedReader(new Inp

25、utStreamReader(bin);String str = read.readLine();for (int i = 0; i < length; i+) ClientMessage oldMsg = clientList.get(i);if (oldMsg.hasClient(receivePacket.getPort(),receivePacket.getAddress() have = true;break;/ 未存在此客戶端if (!have) ClientMessage newMsg = new ClientMessage(Integer.parseInt(str.spl

26、it(":")1.trim(),receivePacket.getPort(),receivePacket.getAddress();messageArea.append("用戶: " + str.split(":")0+ " 進(jìn)入聊天室,其IP地址:"+ receivePacket.getAddress().getHostAddress()+ " 發(fā)送端口:" + newMsg.getSendPort() + " 接收端口:"+ newMsg.getReceivePort(

27、) + " 登錄時間:"+ new Date() + " n");clientList.add(newMsg);sendMessage("熱烈歡迎:" + str.split(":")0 + " IP:"+ receivePacket.getAddress().getHostAddress()+ " 加入聊天室!n"); else / 用戶已經(jīng)存在sendMessage(str);read.close();bin.close(); catch (Exception e) /

28、/e.printStackTrace();messageArea.append(e + "sendmessage errorn");/ 服務(wù)器端發(fā)送消息給客戶端public void sendToClient() /服務(wù)器 廣播消息public void sendMessage(String str) ByteArrayOutputStream out = new ByteArrayOutputStream();PrintStream pout = new PrintStream(out);pout.print(str);byte buf = out.toByteArray

29、(); / 緩沖區(qū)int length = clientList.size();try / 轉(zhuǎn)發(fā)給每一個在線用戶for (int i = 0; i < length; i+) ClientMessage msg = clientList.get(i);sendPacket = new DatagramPacket(buf, buf.length,msg.getClientIp(), msg.getReceivePort();sendSocket.send(sendPacket); catch (IOException e) e.printStackTrace();buf = null;c

30、lass ClientMessage private int receivePort; / 客戶端的接收端口private int sendPort; / 客戶端的發(fā)送端口private InetAddress clientIp; / 客戶端的IPpublic ClientMessage(int receivePort, int sendPort, InetAddress clientIp) this.receivePort = receivePort;this.clientIp = clientIp;this.sendPort = sendPort;public int getReceive

31、Port() return receivePort;public InetAddress getClientIp() return clientIp;public int getSendPort() return sendPort;public boolean hasClient(int sendPort, InetAddress ip) if (ip.getHostAddress().equals(this.getClientIp().getHostAddress()&& sendPort = this.getSendPort() return true;return false;2.6 程序調(diào)試及運行結(jié)果2.6.1 調(diào)試前的準(zhǔn)備安裝jdk并在計算機(jī)的環(huán)境變量中配置好java環(huán)境。使用的實驗環(huán)境是Windows 7,Eclipse SDK 版本:,。2.6.2 程序調(diào)試過程啟動eclipse,單機(jī)測試。首先在主機(jī)上運行服務(wù)器端程序,再在器上運行3個客戶端程序。然后進(jìn)入到用戶的圖形用戶界面,輸入服務(wù)器的IP,進(jìn)行連接,如果連接成功,則客戶端就可以通過與服務(wù)器端進(jìn)行通信,然后服務(wù)器轉(zhuǎn)發(fā)

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論