版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、一、 課程設(shè)計題目基于P2P的局域網(wǎng)即時通信系統(tǒng)二、 實驗環(huán)境及工具1 計算機:2臺PC機,2 操作系統(tǒng):Windows73 程序設(shè)計語言: java三、 設(shè)計要求1 實現(xiàn)一個圖形用戶界面局域網(wǎng)內(nèi)的消息系統(tǒng)。2 功能:建立一個局域網(wǎng)內(nèi)的簡單的P2P消息系統(tǒng),程序既是服務(wù)器又是客戶,服務(wù)器端口使用3333。a) 用戶注冊及對等方列表的獲取:對等方A啟動后,用戶設(shè)置自己的信息(用戶名,所在組);掃描網(wǎng)段中在線的對等方(3333端口打開),向所有在線對等方的服務(wù)端口發(fā)送消息,接收方接收到消息后,把對等方A加入到自己的用戶列表中,并發(fā)應(yīng)答消息;對等方A把回應(yīng)消息的其它對等方加入用戶列表。雙方交換的消息
2、格式自己根據(jù)需要定義,至少包括用戶名、IP地址。b) 發(fā)送消息和文件:用戶在列表中選擇用戶,與用戶建立TCP連接,發(fā)送文件或消息。3 用戶界面:界面上包括對等方列表;消息顯示列表;消息輸入框;文件傳輸進程顯示及操作按鈕或菜單。四、 設(shè)計內(nèi)容與步驟1 學(xué)習(xí)Socket和TCP的基本原理和通信機制;2 功能設(shè)計和界面設(shè)計3 服務(wù)器功能的設(shè)計和實現(xiàn) 4 客戶功能的設(shè)計和實現(xiàn)5 課程設(shè)計任務(wù)說明書五、 系統(tǒng)設(shè)計1. 基本功能(1)當(dāng)某個用戶上線后以自己的主機ip進入聊天室以后,自己的ip就會在“當(dāng)前聊天者”的列表顯示出來 (2)用戶通過“發(fā)送”按鈕可以將自己的要“發(fā)送的話”發(fā)送出去,同個局域網(wǎng)的在線用
3、戶都會收到 (3)通過雙擊用戶的ip,彈出一對一聊天對話框。輸入要說的話,可以喝某個用戶進行一對一的聊天。 (4)通過“發(fā)送文件”按鈕,彈出文件選擇框,選擇文件??梢园盐募l(fā)送給跟你正在聊天的用戶。 (5)如果有一個用戶發(fā)送文件或者話給另外一個用戶,這時候另外一個用戶用收到一個提醒小窗口。這時候就可以打開對話框接受文件和話。 (6)如果對方用戶已經(jīng)成功接受了你的發(fā)送的文件,這時候會彈出對話框提醒你。2. 結(jié)構(gòu)關(guān)系圖3. 詳細設(shè)計(1) 多播的實現(xiàn)多播主要是通過UDP協(xié)議實現(xiàn)的。在java中,可以通過.DatagramPacket 這個類來實現(xiàn)的。只要你傳入廣播地址和內(nèi)容以及端口,在這個廣播地址
4、里面的在線用戶都可以收到這個消息。(2) 一對一發(fā)送的實現(xiàn)。因為一對一一定要有2臺主機相連。所以我的實現(xiàn)的方法是先通過UDP發(fā)送3個字節(jié)探測是不是連接成功,如果成功才用TCP來連接。這里主要是用到j(luò)ava的socket(3) 每個類的主要作用PPfriend:主要是程序的啟動類。繼承了JFrameMywindow: 畫出主界面。繼承了JFrameDialog: 畫出一對一聊天界面。繼承了JFrameReceiveIp:獲得所有在線用戶的ip以及消息。繼承了ThreadReceive: 接收文件。繼承了Thread 繼承了ThreadRecevieToOne:建立TCP連接,接受某人的消息Sen
5、dFile:發(fā)送文件。繼承了ThreadSendIp:發(fā)送自己的ip。繼承了ThreadSendSMG:群發(fā)消息。繼承了ThreadSendToOne: 建立連接,確定發(fā)送文件,查找發(fā)送文件,發(fā)送給某人消息。繼承了ThreadSocketStatus:當(dāng)前程序的狀態(tài):例如接受群消息。六、 代碼清單1. Dialog.java: package com.qgjava.p2p;/* * 當(dāng)雙擊“當(dāng)前聊天者列表”中的IP,彈出的對話框界面 * author yangchuxi * */public class Dialog extends javax.swing.JFrame TextArea ch
6、at;TextField sendchat;Button sbutton,fbutton,refile;public Dialog(String name) super(name);Label title=new Label("密函:");/創(chuàng)建個只讀文本,用來顯示別人發(fā)過來的消息chat=new TextArea(20,20);chat.setEditable(false);/創(chuàng)建個允許編輯的文本,用來發(fā)送一對一消息sendchat=new TextField(25);/sendchat.setEditable(true);sbutton=new Button("
7、;發(fā)送");fbutton=new Button("發(fā)送文件");refile=new Button("接收文件");refile.setEnabled(false);Panel p=new Panel(new FlowLayout(FlowLayout.LEFT);/setLayout(new BorderLayout();setBackground(Color.YELLOW);setTitle("一對一聊天"); setSize(400, 200); setLocation(450, 100); setResizable
8、(false); add("North",title);add("Center",chat);p.add(sendchat);p.add(sbutton);p.add(fbutton);p.add(refile);add("South",p);/add("East",sendchat);addWindowListener(new WindowAdapter()public void windowClosed(WindowEvent e)e.getWindow().dispose(););setVisible(tru
9、e);2. Mywindow.java package com.qgjava.p2p;/用程序可以將其他組件放在面板提供的空間內(nèi)class Apanel extends PanelTextArea chat;APanel2 aPanel2;public Apanel()/創(chuàng)建個只讀文本chat=new TextArea(40,40);chat.setEditable(false);aPanel2=new APanel2();/布置容器的邊框布局setLayout(new BorderLayout();add("West",chat);add("East"
10、,aPanel2);class APanel2 extends Paneljava.awt.List list;APanel2()/List 組件為用戶提供了一個可滾動的單選文本項列表,list=new List(25,false);setLayout(new BorderLayout();add("Center",list);add("North",new Label("當(dāng)前聊天者列表");add("East",new Label();add("South",new Label("雙
11、擊一個人的昵稱可以進行交談");class BPanel extends PanelTextField msg;Button button1,button2,button3,button4,button5;public BPanel()msg=new TextField(30);button1=new Button("發(fā)送");button2=new Button("刷新談話區(qū)");button3=new Button("刷新在線用戶"); / button2.addActionListener(new Myw_reflas
12、h_msg_adapter();setLayout(new FlowLayout(FlowLayout.LEFT);add(new Label("發(fā)送的話");add(msg);/* * 顯示聊天界面的各個模塊 * author yangchuxi * */public class Mywindow extends JFrame/PPfriend friend=new PPfriend(); Label person; Apanel pa; BPanel pb; public Mywindow() super(); person=new Label("聊天記錄&q
13、uot;); pa=new Apanel(); pb=new BPanel(); setLayout(new BorderLayout(); setBackground(Color.YELLOW); setSize(550, 450); setLocation(450, 100); setResizable(false); add("North",person); add("Center",pa); add("South",pb); /此類存在的目的是方便創(chuàng)建偵聽器對象 addWindowListener(new WindowAdap
14、ter() public void windowClosing(WindowEvent e) System.exit(1); ); this.setTitle("楊初喜3108006588"); setVisible(true); /* * "發(fā)送"的按鍵處理 * author yangchuxi * */class Myw_send_adapter implements ActionListener SocketStatus status=new SocketStatus();/Overridepublic void actionPerformed(A
15、ctionEvent e) System.out.println("fasonfaoononon."); status.setStatus(SocketStatus.RECIVE_ALL_MSG); /* * "刷新談話區(qū)"的按鍵處理 * author yangchuxi * */class Myw_reflash_msg_adapter implements ActionListener SocketStatus status=new SocketStatus();/Overridepublic void actionPerformed(ActionE
16、vent e) status.status=SocketStatus.RECIVE_ALL_MSG; /* * "刷新在線用戶"的按鍵處理 * author yangchuxi * */class Myw_reflash_people_adapter implements ActionListener SocketStatus status=new SocketStatus();/Overridepublic void actionPerformed(ActionEvent e) status.status=SocketStatus.RECIVE_IP; 3. PPfrie
17、nd.java/* * 系統(tǒng)線程主類 * author yangchuxi * */public class PPfriend extends JFrame public Mywindow myw ; public RecevieToOne recevietoone; SocketStatus socketStatus=new SocketStatus(); public Dialog qq=null; /定義廣播的地址 String ips="192.168.1.255" /發(fā)送者的ip public String sendIp=null; /本地的ip public S
18、tring localip=null; boolean send=false; boolean isstart=false; /發(fā)送文件的lujing String sendfilepath=null; /接收文件的路徑 String savefilepath=null; String recivename=null; File files; /一對一發(fā)送的信息 String sendtooneMSG=null; /一對一接收的消息 String recivetooneMSG=null; /所有在線用戶的ip HashSet listhastset=new HashSet(); boolean
19、 packFrame = false; RecevieSMG recevieSMG=new RecevieSMG(this); SendSMG sendSMG=new SendSMG(this); SendIp sendip=new SendIp(this); boolean issendfile=false; SendFile sendFile ; Recevie recevie;/ SendThread sendThread boolean flag=true;/ public PPfriend(String sendfilepath) /sendFile=new SendFile(thi
20、s, sendfilepath);/sendFile.start();/public PPfriend() myw=new Mywindow(); this.actionPerformed(this);if(flag)/發(fā)送自己的ip sendip.start(); /接收所有在線用戶的ip ReceiveIp receiveIp=new ReceiveIp(this); receiveIp.start(); recevietoone=new RecevieToOne(this); recevietoone.start();flag=false; if (packFrame) /調(diào)整此窗口的大
21、小,以適合其子組件的首選大小和布局 myw.pack(); else /驗證此容器及其所有子組件。 myw.validate(); / Center the window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = myw.getSize(); if (frameSize.height > screenSize.height) frameSize.height = screenSize.height; if (frameSize.width > s
22、creenSize.width) frameSize.width = screenSize.width; myw.setLocation(screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); myw.setVisible(true);public void actionPerformed(PPfriend friend) final PPfriend pfriend;pfriend=friend;/為“發(fā)生”按鍵添加按鍵觸發(fā) myw.pb.button1.addActionLi
23、stener(new ActionListener() Overridepublic void actionPerformed(ActionEvent e) if(isstart=false) sendSMG.start(); isstart=true;send=true;System.out.println("111111111num"+sendSMG.getState();); /為“雙擊聊天”添加按鍵觸發(fā) myw.pa.aPanel2.list.addActionListener(new ActionListener() Overridepublic void act
24、ionPerformed(ActionEvent e) System.out.println("list.");qq=new Dialog("一對一聊天");pfriend.sendIp=myw.pa.aPanel2.list.getSelectedItem();System.out.println("sendIP."+sendIp);if(recevietoone.getip!=null)qq.refile.setEnabled(true);if(pfriend.recivetooneMSG!=null)qq.chat.append
25、(recivetooneMSG+"n");/為“發(fā)送”添加觸發(fā)按鈕qq.sbutton.addActionListener(new ActionListener() Overridepublic void actionPerformed(ActionEvent e) sendtooneMSG=qq.sendchat.getText();SendToOne sendToOne=new SendToOne(pfriend, true, sendtooneMSG);sendToOne.start();); /為發(fā)送文件添加觸發(fā)按鈕qq.fbutton.addActionListe
26、ner(new ActionListener() Overridepublic void actionPerformed(ActionEvent arg0) System.out.println("發(fā)送文件.");JFileChooser jFileChooser=new JFileChooser();jFileChooser.setMultiSelectionEnabled(false); jFileChooser.showOpenDialog(qq); files =jFileChooser.getSelectedFile(); sendfilepath=files.g
27、etAbsolutePath(); jFileChooser.setToolTipText(sendfilepath); /開始發(fā)送文件 System.out.println("sendfilepath."+sendfilepath); issendfile=true; sendFile=new SendFile(pfriend, sendfilepath); sendFile.start();/ flag=false;/ new PPfriend(sendfilepath););/為接收文件添加觸發(fā)按鈕/ if(qq!=null)/ System.out.println(
28、"recive.button ./."); qq.refile.addActionListener(new ActionListener() Overridepublic void actionPerformed(ActionEvent e) System.out.println("jiejie.");JFileChooser jFileChooser=new JFileChooser();File savefile;jFileChooser.showSaveDialog(qq);savefile=jFileChooser.getSelectedFile
29、();if(savefile!=null)savefilepath=savefile.getAbsolutePath();System.out.println("savepath."+savefilepath);recevie=new Recevie(pfriend, savefilepath);recevie.start(););/ );/public void a()/SendFile sendFile=new SendFile(this, sendfilepath);/public static void main(String args) /Swing 實用方法的集
30、合導(dǎo)致 doRun.run() 在 AWT 事件指派線程上異步執(zhí)行。 SwingUtilities.invokeLater(new Runnable() public void run() try /UIManager 管理當(dāng)前外觀、可用外觀集合、外觀更改時被通知的 PropertyChangeListeners、 /外觀默認(rèn)值以及獲取各種默認(rèn)值的便捷方法 UIManager.setLookAndFeel(UIManager. getSystemLookAndFeelClassName(); catch (Exception exception) exception.printStackTra
31、ce(); /SocketStatus status=new SocketStatus(); new PPfriend(); );4. ReceiveIp.javapackage com.qgjava.p2p;/* * 獲得所有在線用戶的ip,群發(fā)或者單發(fā)的聊天記錄等操作 * author yangchuxi * */public class ReceiveIp extends Thread public ReceiveIp(PPfriend friend) super();this.friend = friend;PPfriend friend;SocketStatus socketStat
32、us=new SocketStatus(); / Vector vectorip=new Vector(); String msg; String sendip="" boolean socket=false;public void run() byte inbuf=new byte50;/某認(rèn)緩沖的大小/此類表示用來發(fā)送和接收數(shù)據(jù)報包的套接字 DatagramSocket socket; try socket = new DatagramSocket(3333); while(true)try /此類表示數(shù)據(jù)報包。 構(gòu)造 DatagramPacket,用來接收長度為 le
33、ngth 的數(shù)據(jù)包DatagramPacket packet=new DatagramPacket(inbuf, inbuf.length);synchronized (socket) try /System.out.println("11111111111111111");/從此套接字接收數(shù)據(jù)報包socket.receive(packet);/System.out.println("2222222222"); catch (Exception e) e.printStackTrace();/System.out.println("run111
34、11111111111111111111111111"+"length:"+packet.getLength()+"port"+packet.getPort()+"addr"+packet.getAddress().toString();/接受數(shù)據(jù) msg=new String(packet.getData(); for (int i = 0; i < inbuf.length; i+) inbufi=(byte)0; sendip=packet.getAddress().toString(); sendip=send
35、ip.substring(1);/ System.out.println("sendip"+sendip);/ System.out.println("msg"+msg);/ System.out.println("receive."); String status = msg.split(":"); System.out.println(status0); switch (Integer.parseInt(status0) case 0x01:String result = msg.split("s&q
36、uot;);/ System.out.println(result.length); for (int x=0; x<result.length; x+) / System.out.println("xxxx"+resultx); resultx=resultx.substring(2); /用這個hashset可以不重復(fù)的添加元素 if(friend.listhastset.add(resultx) friend.myw.pa.aPanel2.list.add(resultx); break;case 0x02:/System.out.println("m
37、sgmsg222222222222222"); if(msg!=null)msg=msg.substring(1); friend.myw.pa.chat.append(sendip+"說"+msg); friend.myw.pa.chat.append("n"); / ac.play(); break;default:break;/ socket.close();/ try /sleep(1000);/ catch (InterruptedException e) / TODO Auto-generated catch block/e.pri
38、ntStackTrace();/ catch (Exception e) / TODO Auto-generated catch blocke.printStackTrace(); catch (Exception e1) e1.printStackTrace(); 5. Recevie.java package com.qgjava.p2p;/* * 用于接收文件等操作 * author yangchuxi * */public class Recevie extends Thread private String filepath=null; PPfriend friend=null; I
39、netAddress addr; public Recevie(PPfriend friend,String savepath) this.friend=friend; filepath=savepath; public void doclient() int length; File file=new File(filepath); /創(chuàng)建一個向指定 File 對象表示的文件中寫入數(shù)據(jù)的文件輸出流。 FileOutputStream fileOutputStream; Socket socket;try fileOutputStream = new FileOutputStream(file
40、);if(friend.recevietoone.getip!=null) try /在給定主機名的情況下確定主機的 IP 地址addr=InetAddress.getByName(friend.recevietoone.getip);try /此類實現(xiàn)客戶端套接字創(chuàng)建一個流套接字并將其連接到指定 IP 地址的指定端口號socket = new Socket(addr,4444);try/向文本輸出流打印對象的格式化表示形式,刷新輸出緩沖區(qū) /BufferedWriter:將文本寫入字符輸出流,緩沖各個字符,從而提供單個字符、數(shù)組和字符串的高效寫入 PrintWriter out=new Pr
41、intWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),true); InputStream netin=socket.getInputStream(); InputStream in=new DataInputStream(new BufferedInputStream(netin); OutputStream netout=socket.getOutputStream(); OutputStream doc=new DataOutputStream(netout); byte buf=new
42、byte2048; /從輸入流中讀取一定數(shù)量的字節(jié),并將其存儲在緩沖區(qū)數(shù)組 buf中。 length=in.read(buf); while(length!=(-1)/是否讀完所有的數(shù)據(jù) /將指定 byte 數(shù)組中從偏移量 off 開始的 len 個字節(jié)寫入此文件輸出流 fileOutputStream.write(buf, 0, length); length=in.read(buf); in.close(); fileOutputStream.close(); finally JOptionPane.showMessageDialog(null, "文件傳輸成功!",n
43、ull,JOptionPane.OK_OPTION); socket.close(); catch (IOException e) e.printStackTrace(); catch (UnknownHostException e) e.printStackTrace(); catch (FileNotFoundException e) e.printStackTrace(); public void run() this.doclient(); 6. RecevieToOne.java package com.qgjava.p2p;/* * 建立TCP連接。判斷是否進行報文發(fā)送,接收某人的
44、消息等操作 * author yangchuxi * */public class RecevieToOne extends Thread DatagramSocket datagramSocket; public String getip=null; PPfriend friend; String msg; public RecevieToOne(PPfriend friend) super(); this.friend=friend; public void run() try byte inbuf=new byte256; /創(chuàng)建數(shù)據(jù)報套接字并將其綁定到本地主機上的指定端口。用UDP可以
45、接收廣播 DatagramSocket socket=new DatagramSocket(8889); System.out.println("recive to one."); /數(shù)據(jù)報包用來實現(xiàn)無連接包投遞服務(wù)。 構(gòu)造 DatagramPacket,用來接收長度為 length 的數(shù)據(jù)包 DatagramPacket packet=new DatagramPacket(inbuf, inbuf.length); socket.receive(packet); /接受數(shù)據(jù) msg=new String(packet.getData(); /返回某臺機器的 IP 地址,此
46、數(shù)據(jù)報將要發(fā)往該機器或者是從該機器接收到的。/ if(msg!=null) getip=packet.getAddress().getHostAddress().toString();/ if(getip!=null && msg!=null) /把緩沖區(qū)清空 for (int i = 0; i < inbuf.length; i+) inbufi=(byte)0; System.out.println("msg."+msg); String status = msg.split(":"); System.out.println(s
47、tatus0); switch (Integer.parseInt(status0) case 0x03: friend.recivetooneMSG=msg.substring(2); JOptionPane.showMessageDialog(null, getip+"發(fā)消息給您,請雙擊它的ip以便接收",null,JOptionPane.OK_OPTION); break; case 0x04:/ if(friend.qq!=null)/ JOptionPane.showMessageDialog(null, getip+"發(fā)文件給您,請按接收按鈕接收",null,JOptionPane.OK_OPTION);/ friend.qq.refile.setEnabled(true);/ else JOptionPa
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度鍋爐設(shè)備定期維護保養(yǎng)與安全檢查合同
- 銅陵2025年安徽銅陵市公安局警務(wù)輔助人員招聘112人筆試歷年參考題庫附帶答案詳解
- 貴州2025年貴州農(nóng)業(yè)職業(yè)學(xué)院招聘29人筆試歷年參考題庫附帶答案詳解
- 莆田2025年福建莆田市仙游縣事業(yè)單位高層次人才招聘10人筆試歷年參考題庫附帶答案詳解
- 肇慶2025年廣東肇慶懷集縣招聘鄉(xiāng)村公益性崗位工作人員111人筆試歷年參考題庫附帶答案詳解
- 江蘇中國中煤能源集團有限公司江蘇分公司2025屆高校畢業(yè)生第二次招聘6人筆試歷年參考題庫附帶答案詳解
- 2025年中國天門冬素市場調(diào)查研究報告
- 2025年中國冰棍市場調(diào)查研究報告
- 2025至2031年中國高壓氣動注油器行業(yè)投資前景及策略咨詢研究報告
- 2025至2031年中國醇基綠色涂料行業(yè)投資前景及策略咨詢研究報告
- 《大健康解讀》課件
- 2024-2025學(xué)年成都市樹德東馬棚七年級上英語期末考試題(含答案)
- 2025年度交通運輸規(guī)劃外聘專家咨詢協(xié)議3篇
- 2024年04月北京中信銀行北京分行社會招考(429)筆試歷年參考題庫附帶答案詳解
- 專項債券培訓(xùn)課件
- 中央企業(yè)人工智能應(yīng)用場景案例白皮書(2024年版)-中央企業(yè)人工智能協(xié)同創(chuàng)新平臺
- 《會務(wù)的組織和管理》課件
- 《倒虹吸管安全評價導(dǎo)則》
- 2025年中國濕度傳感器行業(yè)深度分析、投資前景、趨勢預(yù)測報告(智研咨詢)
- 人民調(diào)解知識課件
- 《儒林外史》(第13-30回)-初中整本書閱讀系列之《儒林外史》
評論
0/150
提交評論