基于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ù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

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

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

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

4、地交付上層的應(yīng)用進(jìn)程,一次交付一個(gè)完整的報(bào)文。 圖1.1UDP基本工作過程1.2 關(guān)鍵技術(shù)1.2.1 服務(wù)器端Socket的實(shí)現(xiàn)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地址和端口號組成,為進(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é)

5、議,即面向連接的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ú)編址和路由的。從一臺機(jī)器發(fā)送到另一臺機(jī)器的多個(gè)包可能選擇不同的路由,也可能按不同的順序到達(dá)。 在DatagramSocket上總是啟用UDP廣播發(fā)送。為了接收廣播包,應(yīng)該將 DatagramSocket綁定到通配符地址。在某些實(shí)現(xiàn)中,將DatagramSocket綁定到一個(gè)更加具體

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

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

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

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

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

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

12、器界面,監(jiān)聽客戶端連接狀況并可發(fā)送服務(wù)器消息。2.5 實(shí)現(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

13、,sendField,receivePortField, 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 rece

14、ivePacket = null, 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 Thread(this

15、).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 = new DatagramPacke

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

17、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) messageArea.append(空消息 + n);continue;ByteArrayIn

18、putStream 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(迎:/)messageArea.append(n);read.close();bin.close(); catch (Exception e

19、) 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.inputIP(); 服務(wù)端端代碼:package udp;import java.io.*;import java.awt.*;import java.awt.event.*;import .

20、*;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, messageLabel;private TextArea messageArea; / 消息框,顯示用戶登錄信息private TextField sendField; / 輸入聊天內(nèi)容的文本框pri

21、vate Button sendButton; / 發(fā)送按鈕private DatagramSocket receiveSocket = null, sendSocket = null;private DatagramPacket receivePacket = null, sendPacket = null;private int serverReceivePort = 6666; / 服務(wù)器端的接收端口private List clientList = new ArrayList(); / 保存連接的客戶端信息boolean isServer = true;/ 程序主入口public st

22、atic void main(String args) Server server = new Server();server.launchFrame();server.start(); / 啟動服務(wù)器server.receiveMessage(); / 接收信息/ 服務(wù)端界面初始化public void launchFrame() / 事件監(jiān)聽處理public void actionPerformed(ActionEvent e) / 啟動服務(wù)器public void start() try sendSocket = new DatagramSocket(6660);/ 服務(wù)器發(fā)送端口 ca

23、tch (Exception e) messageArea.append(e + n);/ 服務(wù)器接收消息public void receiveMessage()try receiveSocket = new DatagramSocket(serverReceivePort);/ 服務(wù)器接受端口while (true) byte buf = new byte200;receivePacket = new DatagramPacket(buf, buf.length);receiveSocket.receive(receivePacket);int length = clientList.siz

24、e();boolean have = false;ByteArrayInputStream bin = new ByteArrayInputStream(receivePacket.getData();BufferedReader read = new BufferedReader(new InputStreamReader(bin);String str = read.readLine();for (int i = 0; i length; i+) ClientMessage oldMsg = clientList.get(i);if (oldMsg.hasClient(receivePac

25、ket.getPort(),receivePacket.getAddress() have = true;break;/ 未存在此客戶端if (!have) ClientMessage newMsg = new ClientMessage(Integer.parseInt(str.split(:)1.trim(),receivePacket.getPort(),receivePacket.getAddress();messageArea.append(用戶: + str.split(:)0+ 進(jìn)入聊天室,其IP地址:+ receivePacket.getAddress().getHostAdd

26、ress()+ 發(fā)送端口: + newMsg.getSendPort() + 接收端口:+ newMsg.getReceivePort() + 登錄時(shí)間:+ 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) / /e.print

27、StackTrace();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(); / 緩沖區(qū)int length

28、= clientList.size();try / 轉(zhuǎn)發(fā)給每一個(gè)在線用戶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;class ClientMessage privat

29、e 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 getReceivePort() return receivePort

30、;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)試及運(yùn)行結(jié)果2.6.1 調(diào)試前的準(zhǔn)備安裝jdk1.6.0并在計(jì)算機(jī)的環(huán)境變量中配置好java環(huán)境。使用的實(shí)驗(yàn)環(huán)境是Windows 7,Eclipse SDK 版本:3.2.0,。2.6.2 程序調(diào)試過程啟動eclipse,單機(jī)測試。首先在主機(jī)上運(yùn)行服務(wù)器端程序,再在器上運(yùn)行3個(gè)客戶端程序。然后進(jìn)入到用戶的圖形用戶界面,輸入服務(wù)器的IP,進(jìn)行連接,如果連接成功,則客戶端就可以通過與服務(wù)器端進(jìn)行通信,然后服務(wù)器轉(zhuǎn)發(fā)通信,實(shí)現(xiàn)了多個(gè)客戶之間的聊天功能。2.6.3 程序運(yùn)行結(jié)果圖2.

溫馨提示

  • 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論