1、 1 一、 课程设计题目 基于 P2P 的局域网即时通信系统 二、 实验环境及工具 1 计算机: 2 台 PC 机, 2 操作系统: Windows7 3 程序设计语言: java 三、 设计要求 1 实现一个图形用户界面局域网内的消息系统。 2 功能:建立一个局域网内的简单的 P2P 消息系统,程序既是服务器又是客户,服务器端口使用 3333。 a) 用户注册及对等方列表的获取:对等方 A 启动后,用户设置自己的信息(用户名,所在组);扫描网段中在线的对等方( 3333 端口打开),向所有在线对等方的服务端口发送消息,接收方接收到消息后,把对等方 A 加入到自己的用户列表中,并发应答 消息;
2、对等方A 把回应消息的其它对等方加入用户列表。双方交换的消息格式自己根据需要定义,至少包括用户名、 IP 地址。 b) 发送消息和文件:用户在列表中选择用户,与用户建立 TCP 连接,发送文件或消息。 3 用户界面:界面上包括对等方列表;消息显示列表;消息输入框;文件传输进程显示及操作按钮或菜单。 四、 设计内容与步骤 1 学习 Socket 和 TCP 的基本原理和通信机制 ; 2 功能设计和界面设计 3 服务器功能的设计和实现 4 客户功能的设计和实现 5 课程设计任务说明书 2 五、 系统设计 1. 基本功能 ( 1)当某个用户上线后以自己的主机 ip 进入聊天室 以后,自己的 ip 就
3、会在“当前聊天者”的列表显示出来 ( 2)用户通过“发送”按钮可以将自己的要“发送的话”发送出去,同个局域网的在线用户都会收到 ( 3)通过双击用户的 ip,弹出一对一聊天对话框。输入要说的话,可以喝某个用户进行一对一的聊天。 ( 4)通过“发送文件”按钮,弹出文件选择框,选择文件。可以把文件发送给跟你正在聊天的用户。 ( 5)如果有一个用户发送文件或者话给另外一个用户,这时候另外一个用户用收到一个提醒小窗口。这时候就可以打开对话框接受文件和话。 ( 6)如果对方用户 已经成功接受了你的发送的文件,这时候会弹出对话框提醒你。 2. 结构关系图 3. 详细设计 ( 1) 多播的实现 3 多播主要
4、是通过 UDP 协议实现的。在 java 中,可以通过.DatagramPacket 这个类来实现的。只要你传入广播地址和内容以及端口,在这个 广播地址里面的在线用户都可以收到这个消息。 ( 2) 一对一发送的实现。 因为一对一一定要有 2 台主机相连。所以我的实现的方法是先通过UDP 发送 3 个字节探测是不是连接成功,如果成功才用 TCP 来连接。这里主要是用到 java 的 socket ( 3) 每 个类的主要作用 PPfriend:主要是程序的启动类。继承了 JFrame Mywindow: 画出主界面。继承了 JFrame Dialog: 画出一对一聊天界面。继承了 JFrame
5、ReceiveIp:获得所有在线用户的 ip以及消息。继承了 Thread Receive: 接收文件。继承了 Thread 继承了 Thread RecevieToOne:建立 TCP 连接,接受某人的消息 SendFile:发送文件。 继承了 Thread SendIp:发送自己的 ip。 继承了 Thread SendSMG:群发消息。 继承了 Thread SendToOne: 建立连接,确定发送文件,查找发送文件,发送给某人消息。 继承了 Thread SocketStatus:当前程序的状态:例如接受群消息。 六、 代码清单 1. Dialog.java: package com.
6、qgjava.p2p; /* 4 * 当双击“当前聊天者列表”中的 IP,弹出的对话框界面 * author yangchuxi * */ public class Dialog extends javax.swing.JFrame TextArea chat; TextField sendchat; Button sbutton,fbutton,refile; public Dialog(String name) super(name); Label title=new Label(“密函 :“); /创建个只读文本,用来显示别人发过来的消息 chat=new TextArea(20,20)
7、; chat.setEditable(false); /创建个允许编辑的文本,用来发送一对一消息 sendchat=new TextField(25); / sendchat.setEditable(true); sbutton=new Button(“发送 “); fbutton=new Button(“发送文件 “); refile=new Button(“接收文件 “); refile.setEnabled(false); Panel p=new Panel(new FlowLayout(FlowLayout.LEFT); /setLayout(new BorderLayout(); s
8、etBackground(Color.YELLOW); setTitle(“一对一聊天 “); setSize(400, 200); setLocation(450, 100); setResizable(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
9、void windowClosed(WindowEvent e) e.getWindow().dispose(); ); setVisible(true); 5 2. Mywindow.java package com.qgjava.p2p; /用程序可以将其他组件放在 面板提供的空间内 class Apanel extends Panel TextArea chat; APanel2 aPanel2; public Apanel() /创建个只读文本 chat=new TextArea(40,40); chat.setEditable(false); aPanel2=new APanel2(
10、); /布置容器的边框布局 setLayout(new BorderLayout(); add(“West“,chat); add(“East“,aPanel2); class APanel2 extends Panel java.awt.List list; APanel2() /List 组件为用户提供了一个可滚动的单选文本项列表 , list=new List(25,false); setLayout(new BorderLayout(); add(“Center“,list); add(“North“,new Label(“当前聊天者列表 “); add(“East“,new Labe
11、l(); add(“South“,new Label(“双击一个人的昵称可以进行交谈 “); class BPanel extends Panel TextField msg; Button button1,button2,button3,button4,button5; public BPanel() msg=new TextField(30); button1=new Button(“发送 “); button2=new Button(“刷新谈话区 “); button3=new Button(“刷新在线用户 “); / button2.addActionListener(new Myw_
12、reflash_msg_adapter(); setLayout(new FlowLayout(FlowLayout.LEFT); add(new Label(“发送的话 “); add(msg); 6 /* * 显示聊天界面的各个模块 * author yangchuxi * */ public class Mywindow extends JFrame /PPfriend friend=new PPfriend(); Label person; Apanel pa; BPanel pb; public Mywindow() super(); person=new Label(“聊天记录 “
13、); 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); /此类存在的目的是方便创建侦听器对象 addWindowListener(new WindowAdapter() public void windowClosing(Wi
14、ndowEvent e) System.exit(1); ); this.setTitle(“杨初喜 3108006588“); setVisible(true); /* * “发送 “的按键处理 * author yangchuxi * */ class Myw_send_adapter implements ActionListener SocketStatus status=new SocketStatus(); / Override 7 public void actionPerformed(ActionEvent e) System.out.println(“fasonfaoonon
15、on.“); status.setStatus(SocketStatus.RECIVE_ALL_MSG); /* * “刷新谈话区 “的按键处理 * author yangchuxi * */ class Myw_reflash_msg_adapter implements ActionListener SocketStatus status=new SocketStatus(); / Override public void actionPerformed(ActionEvent e) status.status=SocketStatus.RECIVE_ALL_MSG; /* * “刷新在线
16、用户 “的按键处理 * author yangchuxi * */ class Myw_reflash_people_adapter implements ActionListener SocketStatus status=new SocketStatus(); / Override public void actionPerformed(ActionEvent e) status.status=SocketStatus.RECIVE_IP; 3. PPfriend.java /* * 系统线程主类 * author yangchuxi * */ public class PPfriend
17、extends JFrame public Mywindow myw ; public RecevieToOne recevietoone; SocketStatus socketStatus=new SocketStatus(); public Dialog qq=null; /定义广播的地址 8 String ips=“192.168.1.255“; /发送者的 ip public String sendIp=null; /本地的 ip public String localip=null; boolean send=false; boolean isstart=false; /发送文件的
18、 lujing String sendfilepath=null; /接收文件的路径 String savefilepath=null; String recivename=null; File files; /一对一发送的信息 String sendtooneMSG=null; /一对一接收的消息 String recivetooneMSG=null; /所有在线用户的 ip HashSet listhastset=new HashSet(); boolean packFrame = false; RecevieSMG recevieSMG=new RecevieSMG(this); Sen
19、dSMG 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(this, sendfilepath); / sendFile.start(); / public PPfriend() myw=ne
20、w Mywindow(); this.actionPerformed(this); if(flag) /发送自己的 ip sendip.start(); /接收所有在线用户的 ip ReceiveIp receiveIp=new ReceiveIp(this); receiveIp.start(); 9 recevietoone=new RecevieToOne(this); recevietoone.start(); flag=false; if (packFrame) /调整此窗口的大小,以适合其子组件的首 选大小和布局 myw.pack(); else /验证此容器及其所有子组件。 my
21、w.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 screenSize.width) frameSize.width = screenSize.width; myw.setLo
22、cation(screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); myw.setVisible(true); public void actionPerformed(PPfriend friend) final PPfriend pfriend; pfriend=friend; /为“发生”按键添加按键触发 myw.pb.button1.addActionListener(new ActionListener() Override public void actionPerf
23、ormed(ActionEvent e) if(isstart=false) sendSMG.start(); isstart=true; send=true; 10 System.out.println(“111111111num“+sendSMG.getState(); ); /为“双击聊天”添加按键触发 myw.pa.aPanel2.list.addActionListener(new ActionListener() Override public void actionPerformed(ActionEvent e) System.out.println(“list.“); qq=n
24、ew 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(recivetooneMSG+“n“); /为“发送”添加触发按钮 qq.sbutton.addActionListener(new ActionListener(
25、) Override public void actionPerformed(ActionEvent e) sendtooneMSG=qq.sendchat.getText(); SendToOne sendToOne=new SendToOne(pfriend, true, sendtooneMSG); sendToOne.start(); ); /为发送文件添加触发按钮 qq.fbutton.addActionListener(new ActionListener() Override public void actionPerformed(ActionEvent arg0) System.out.println(“发送文件 .“); JFileChooser jFileChooser=new JFileChooser(); jFileChooser.setMultiSelectionEnabled(false); jFileChooser.showOpenDialog(qq);