JAVA课程设计实验报告“聊天室”报告

更新时间:2024-02-27 06:01:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

中南大学

《面向对象》课程设计

学生姓名 学生学号 专业班级 指导教师 完成时间

题 目 “聊天室”课程设计(java语言)

目 录

第一章 聊天室的描述-------------------------------------------3

1.1聊天室的设计要求-------------------------------------------------------------3 1.2聊天室的基本功能-------------------------------------------------------------3 1.3设计所用参考资料-------------------------------------------------------------6

第二章 聊天室的设计-------------------------------------------6

2.1聊天室的粗略设计分析-------------------------------------------------------6 2.2聊天室的具体设计分析-------------------------------------------------------7

第三章 聊天室的实现-------------------------------------------10

3.1聊天室所使用的类及功能的实现-----------------------------------------10

第四章 聊天室的运行-------------------------------------------30 第五章 课程设计总结---------------------------------------------31

5.1开发中所遇到的问题-----------------------------------------------------------31 5.2问题分析与解决方法-----------------------------------------------------------32 5.3经验与教训------------------------------------------------------------------------32

- 2 -

第一章 聊天室的描述

1 .1聊天室的设要求

当今社会,网络技术越来越发展,可以说,二十一世纪就是网络的世纪。网络迅猛发展,势不可挡。为了实现资源共享,各式各样的网站发展迅速,各种各样的聊天工具不断更新。某公司希望通过一个聊天工具加强员工和客户之间的沟通和交流。所以制作一个聊天室势在必行。

为了实现一个更好的网络交互平台,各用户之间能够实时方便的传递信息,按照用户对系统的要求不同,可以在聊天室里实现公共聊天,也可以邀几个私交好友私聊,同时提供了两个用户之间能够传送文件。本系统是基于方便用户聊天,传递信息,共享资源,所以系统的功能主要是从以上几个模块着手。

本项目主要是利用JAVA语言制作一个聊天室,采用的是客户/服务器。 二层的C/S结构是指以单一的服务器和局域网为核心,能通过客户端与用户进行直接对话。主要有二大功能:一是它用于检查用户从键盘等输入的数据,显示应用输出的数据。为使用户能直观地进行操作,一般要使用图形用户接口(GUI),操作简单、易学易用。在变更用户接口时,只需改写显示控制和数据检查程序,而不影响其他。检查的内容也只限于数据的形式和值的范围,不包括有关业务本身的处理逻辑。典型的C/S结构有以下特点:

1、服务器负责数据管理及程序处理。 2、客户机负责界面描述和界面显示。 3、客户机向服务器提出处理要求。 4、服务器响应将处理结果返回客户机。 5、使网络数据流量最少。

1. 2聊天室的基本功能

1. 用户注册 2. 用户登录 3. 在线用户列表 4. 用户公聊 5. 用户私聊 6. 好友信息维护 7. 私聊信息的维护 8. 登录日志的维护

9. 用户注销

扩展功能(如果完整实现一个扩展功能,适当加分):

1. 可以切换不同的界面风格 2. 用户可以更改个人资料,寻找密码 3. 表情聊天 4. 文件传递

- 3 -

5. 公聊信息的维护

? 用户注册

第一次用户需要提供个人注册信息,注册的用户名不能重复,密码长度不能少于6位,个人信息必须提供完整,并且存储在数据库中。 ? 用户登录

用户输入用户名和密码,提交给将服务器端的确认,根据从服务器中传过来的确认信息,判断用户登录的情况。并且把此次登录的时间及登录的IP记录在服务器。

如果用户名和密码正确的话,则登录聊天室主界面;如果已经在线,则输出已经在线;否则输出用户名和密码错误,需要重新登录或者注册。 ? 在线用户列表

用户登录之后,需要知道系统中,有哪些用户在线,这样可以方便用户选择与个别用户私聊和传送文件,也可以进行公聊。 ? 用户公聊

用户输入的用户名和密码都正确后,则进入聊天室。聊天主界面主要由四大版块组成:公聊的聊天信息、在线用户列表、好友列表,系统消息和聊天的一些操作。

聊天信息版块设计思想:一种就是将客户的聊天信息写入数据库,一种是将其写入向量中。在本次项目中,要求学员把客户的聊天信息写入数据库中。 ? 用户私聊

如果两个人聊的话题比较隐秘,不想被其他人看到,就要使用私聊。在这里,如果说话对象是所有人的话,不能选择私聊;从当前好友列表中选择了一个用户之后,则私聊对话框应该弹出来。 ? 文件传递

两个用户在聊天过程中,可能需要相互间传送文件。象用户聊天信息和在线用户这样一些信息都是保存在服务器端,然后每个客户读取服务器端向量中的内容,此时服务器与客户端的联系是一对多的,而传送文件是一对一的。所以直接传送,不需要经过服务器端保存。 ? 好友信息维护

在聊天过程中,用户可以选择聊天室的用户加为自己的好友。对于加为好友的用户,可以选择与其进行私聊。私聊的信息用文件保存在客户端。该模块应该包括:

? 添加好友 ? 删除好友 ? 私聊信息的维护

如果两个人聊的话题比较隐秘,不想被其他人看到,就要使用私聊。而且只有好友之间才能进行私聊。要与某用户进行私聊,必须把对方加为好友。与好友之间的聊天信息,应该以文件的方式存储在客户端,不显示在公聊的版面上。

- 4 -

? 登录日志的维护

用户每次登录之后,都记录下用户的登录信息,如登录的时间日期,登陆的IP等。方便用户发现是否号码被盗用。 ? 用户注销

用户可以注销其身份,对于注销后的用户必须在数据库中删除其相应的信息。

1.3设计所用参考资料

Java编程思想(第四版)(机械工业出版社) Java程序设计与问题解决(人民邮电出版社) Java语言最新使用案例教程(清华大学出版社) Java2应用开发指南(第二版)(电子工业出版社) JDK-API-1.5中文版 网上查阅资料

第二章 聊天室的设计

2 . 1聊天室的粗略设计分析

聊天系统平台应有两个部分组成:服务端和客户端。服务端主要完成用户信息的存储、客户端命令的接受与响应以及发送系统消息、信息转发、踢人等服务端应有的功能。客户端主要完成聊天信息的发送与接受、登录、注销等功能。

此c/s系统使用的是TCP/IP协议,应用了如下通讯模式:

- 5 -

. //界面组件及其他变量声明 public Checkin(Socket toServer) { . . . ..

//界面组件初始化 try{ ToServer=toServer;

streamToServer = new ObjectOutputStream(ToServer.getOutputStream()); streamFromServer=new ObjectInputStream(ToServer.getInputStream()); }catch(Exception e){}

this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

} //将Login中建立的socket做参数传递给Checkin public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals(\注册\ {

for(int t=0;t==0;){

if(textField1.getText().equals(\ { JOptionPane.showMessageDialog(null,\用户名不能为空!\ t=1; }

else if(textField3.getText().equals(textField2.getText())==false) { JOptionPane.showMessageDialog(null,\密码不一致!\ t=1; }else{ User user=new User();

user.Name=textField1.getText(); user.Password=textField2.getText(); user.Age=textField4.getText(); user.Email=textField5.getText();

user.sex=(String)checkboxGroup1.getSelectedCheckbox().getLabel(); user.Command=\ try{

streamToServer.writeObject((User)user); fromServerMessage=(User)streamFromServer.readObject();

}catch(Exception ee){JOptionPane.showMessageDialog(null,\数据发送错误!\ if(fromServerMessage.Command.equals(\ {

dispose();

new MainFrame(ToServer,user.Name); }

- 11 -

if(fromServerMessage.Command.equals(\ { JOptionPane.showMessageDialog(null,\用户名已存在!\ t=1; } } } }

if(e.getActionCommand().equals(\取消\ { dispose(); new Login(); }

} //按钮动作的添加及对服务器的信息传

//递和响应

}

主界面类:

public class MainFrame extends JFrame implements ActionListener,Runnable{ . . . . .

//界面组件及其他变量声明

public MainFrame(Socket toServer,String name) { MainFrame1(toServer,name); //构造函数,其中toServer、name为参数 }

public void MainFrame1(Socket toServer,String name) { . . . .

try{ ToServer=toServer;

streamToServer = new ObjectOutputStream(ToServer.getOutputStream()); streamFromServer = new ObjectInputStream(ToServer.getInputStream()); fromServerMessage=(User)streamFromServer.readObject(); streamToServer.flush();

vectorUserList1=(Vector)fromServerMessage.vectorUserList; vectorUserList.setListData(vectorUserList1);

}catch(Exception ee){JOptionPane.showMessageDialog(null,\ Thread thread = new Thread(this); thread.start();

} //建立连接并启动监听线程

- 12 -

public void run(){ try{ for(int t=1;;){ User commandFromServer=(User)streamFromServer.readObject(); String command=commandFromServer.Command; if(command.equals(\ textArea2.append(commandFromServer.Name+\对大家说:\ } if(command.equals(\ textArea2.append(commandFromServer.Name+\对你说:\ } if(command.equals(\ textArea2.append(commandFromServer.Name+\对大家说:大家好!我来了\ vectorUserList.setListData(vectorUserList1); } if(command.equals(\ lessen(); } if(command.equals(\ textArea2.append(\系统消息:\ } JOptionPane.showMessageDialog(null,\用户名不能为空!\ continue; } }catch(Exception e){}

} //监听线程对服务器信息的处理及响应 public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals(\公聊\ sendPublicMessage(); if(e.getSource()==button2) sendPraviteMessage(); if(e.getActionCommand().equals(\注销\ lessen(); dispose(); try{ streamToServer.close(); streamFromServer.close(); ToServer.close(); }catch(Exception ee){} new Login();

- 13 -

} } //对按钮动作的处理及响应 public void sendPublicMessage(){

} //发送公聊信息 public void sendPraviteMessage(){

} //发送私聊信息 public void lessen(){

} //注销事件

服务端:

服务端序列化信息类:

class User implements Serializable { }

服务器界面类:

String Name;//用户名 String Password;//密码 String Email;//e-mail String Age;//年龄 String sex;//

性别

String Message;//要传递的信息 Vector vectorUserList;//在线用户列表

String Command; //命令标识

public class Server extends JFrame {

. . .

. //组件及变量的定义 public Server() {

initComponents(); //构造方法,初始化组件 }

private void initComponents() {

//组件初始化 try {

//建立InetAddress对象 InetAddress intel=InetAddress.getLocalHost();

- 14 -

String SerIp=intel.getHostAddress(); jLabel3.setText(\服务器:\ }

catch(UnknownHostException e2) {

System.out.println(\发生错误!\ }

jPanel1.add(jLabel3);

jLabel5.setText(\ 0个客户\ jPanel1.add(jLabel5);

jList1.setModel(new AbstractListModel() { String[] strings = {};

public int getSize() { return strings.length; }

public Object getElementAt(int i) { return strings[i]; } });

jList1.setFont(new Font(\ jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); jList1.addMouseListener(new MouseAdapter() {

public void mousePressed(MouseEvent evt) {

if (evt.getClickCount()==1) { BlackList=(String)jList1.getSelectedValue(); } } });

jScrollPane1.setViewportView(jList1); jPanel1.add(jScrollPane1); jPanel1.add(jLabel1);

getContentPane().add(jPanel1); commandMenu.setText(\选项\ msgMenuItem.setText(\系统消息\ msgMenuItem.setBorder(null);

msgMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { msgMenuItemActionPerformed(evt); } });

commandMenu.add(msgMenuItem); kickMenuItem.setText(\踢人\ kickMenuItem.setBorder(null);

kickMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) {

- 15 -

kickMenuItemActionPerformed(evt); } });

commandMenu.add(kickMenuItem); menuBar.add(commandMenu); setJMenuBar(menuBar); startServer(); pack(); }

private void msgMenuItemActionPerformed(ActionEvent evt) //系统消息事件 { try {

User toUserMessage=new User();

String Mesage=JOptionPane.showInputDialog(null,\请输入内容:\系统消息\TION_MESSAGE); toUserMessage.Message=\系统消息:\ toUserMessage.Command=\ for(int i=0;i

streamToUser=(ObjectOutputStream)Server.vectorStreamToUser.elementAt(i);JOptionPane.showMessageDialog(null,\用户名不能为空!4\ streamToUser.writeObject((User)toUserMessage);JOptionPane.showMessageDialog(null,\用户名不能为空!5\ streamToUser.flush(); } }

catch(IOException e){} }

private void kickMenuItemActionPerformed(ActionEvent evt) //踢人事件 { Object obj=evt.getSource(); try { if(obj==kickMenuItem) { BlackList=JOptionPane.showInputDialog(null,\请输入用户名:\系统消息\TION_MESSAGE);

- 16 -

} User toUserMessage=new User(); for(int i=0;i

if(BlackList.equals(Server.vectorUserList.elementAt(i))) { toUserMessage.Command=\ toUserMessage.Message=\系统消息:对不起!你已被踢出!\\n\ } else{ JOptionPane.showInputDialog(null,\无此用户!\ } ObjectOutputStream

streamToUser=(ObjectOutputStream)Server.vectorStreamToUser.elementAt(i);JOptionPane.showMessageDialog(null,\用户名不能为空!1\ streamToUser.writeObject((User)toUserMessage);JOptionPane.showMessageDialog(null,\用户名不能为空!2\ streamToUser.flush();JOptionPane.showMessageDialog(null,\用户名不能为空!3\

} Server.vectorStreamToUser.removeElementAt(Server.vectorUserList.indexOf(BlackList)); Server.vectorUserList.removeElement(BlackList);

jLabel5.setText(\共有:\个客户在线\ BlackList=\ }

catch(IOException e){} }

private void stopServer() //关闭服务器的服务 { String Message=\服务器即将关闭!\ try {

User toUserMessage=new User();

toUserMessage.Command=\ toUserMessage.Message=Message;

for(int i=0;i

streamToUser=(ObjectOutputStream)Server.vectorStreamToUser.elementAt(i); streamToUser.writeObject((User)toUserMessage); streamToUser.flush();

- 17 -

} }

catch(IOException e){} try {

Thread.sleep(5000); }

catch(InterruptedException e){} System.exit(0); }

private void startServer() {

new AppServer(); }

private void exitForm(WindowEvent evt) {

stopServer(); System.exit(0); }

public static void main(String args[]) {

new Server().show(); }

class AppServer extends Thread //启动服务器服务,用于监听客

//户端的连接及命令

{ public AppServer() { try { serverSocket = new ServerSocket(1207);

InetAddress intel=InetAddress.getLocalHost(); String SerIp=intel.getHostAddress();

System.out.println(\服务器:\ } catch(IOException e) { System.out.println(\

- 18 -

} System.out.println(\服务端已启动......\ this.start(); } public void run() { try { while(true) { Socket UserSocket = serverSocket.accept(); connection con = new connection(UserSocket); } } catch(IOException e) { System.out.println(\ } } }

建立连接类:

class connection extends Thread { User fromUserMessage=new User(); User toUserMessage=new User(); Socket netUser; ObjectInputStream streamFromUser; ObjectOutputStream streamToUser;

boolean existName,existPassword; String onlineNumber=\ public connection(Socket UserSocket) //建立连接 { netUser=UserSocket; try { streamFromUser = new ObjectInputStream(netUser.getInputStream()); streamToUser = new ObjectOutputStream(netUser.getOutputStream()); } catch(IOException e) {

- 19 -

try { netUser.close(); } catch(IOException e1) { System.out.print(\ return; } } this.start(); }

public boolean validateName(String name) //判断用户名是否已存在 { boolean validate; String recode,message; FileInputStream fsread; InputStreamReader inputread; BufferedReader bfread; validate=false; try

{

fsread=new FileInputStream(\ inputread=new InputStreamReader(fsread); bfread=new BufferedReader(inputread); while((recode=bfread.readLine()) != null) { StringTokenizer st = new StringTokenizer(recode,\ while (st.hasMoreTokens()) {

message=st.nextToken(); if(message.equals(name)) { validate=true; break; } break;

} } }

catch(FileNotFoundException e) { System.out.println(\数据存储文件读取错误!\

- 20 -

}

catch(IOException e) {

System.out.println(\ }

return validate; }

public boolean validatePassword(String password) //判断密码是否正确 { boolean validate; String recode,message; FileInputStream fsread; InputStreamReader inputread; BufferedReader bfread; validate=false; try

{

fsread=new FileInputStream(\ inputread=new InputStreamReader(fsread); bfread=new BufferedReader(inputread); while((recode=bfread.readLine()) != null) { StringTokenizer st = new StringTokenizer(recode,\ while (st.hasMoreTokens()) {

message=st.nextToken(); message=st.nextToken(); if(message.equals(password)) { validate=true; break; } break; } } }

catch(FileNotFoundException e) { System.out.println(\数据存储文件读取错误!\ }

catch(IOException e) {

- 21 -

System.out.println(\数据存储文件读取错误!\ }

return validate; }

public void run() // 监听客户端信息 { try { for(;;) { String ButtonMessage; fromUserMessage=(User)streamFromUser.readObject(); ButtonMessage=fromUserMessage.Command; existName=validateName(fromUserMessage.Name); existPassword=validatePassword(fromUserMessage.Password); if(ButtonMessage.equals(\ { Login1(); //注册 } if(ButtonMessage.equals(\ { Enter1(); //登陆 }

if(ButtonMessage.equals(\ { Leave1(); //注销 }

if(!onlineNumber.equals(\ { Updating1(fromUserMessage.Name); //用户改变 }

if(ButtonMessage.equals(\ { Message1(); //发送信息 }

continue; } } catch(IOException e){}

catch(ClassNotFoundException e){} try

- 22 -

{

streamFromUser.close(); streamToUser.close(); netUser.close(); }

catch(IOException e){} }

public void Login1() //注册事件 { try {

if(existName) { toUserMessage.Command=\ streamToUser.writeObject((User)toUserMessage); streamToUser.flush(); }

else { RandomAccessFile UserObj=new RandomAccessFile(\ UserObj.seek(UserObj.length()); UserObj.writeBytes(fromUserMessage.Name+\ +fromUserMessage.sex+\ onlineNumber=\ toUserMessage.Command=\ toUserMessage.Name=fromUserMessage.Name; toUserMessage.Message=\系统消息:大家欢迎\加入!\

Server.vectorUserList.addElement(fromUserMessage.Name);

toUserMessage.vectorUserList=Server.vectorUserList; streamToUser.writeObject((User)toUserMessage); streamToUser.flush(); Server.vectorStreamToUser.addElement(streamToUser); jLabel5.setText(\ \个客户\ jList1.setListData(Server.vectorUserList); } }

- 23 -

catch(IOException e){JOptionPane.showMessageDialog(null,\ }

public void Enter1() //登陆事件 { try {

if(existName && existPassword) { onlineNumber=\ toUserMessage.Command=\ toUserMessage.Name=fromUserMessage.Name; toUserMessage.Message=\系统消息:大家欢迎\加入!\ Server.vectorUserList.addElement(fromUserMessage.Name);

toUserMessage.vectorUserList=Server.vectorUserList; streamToUser.writeObject((User)toUserMessage); streamToUser.flush(); Server.vectorStreamToUser.addElement(streamToUser); jLabel5.setText(\ \个客户\ jList1.setListData(Server.vectorUserList); } }

catch(IOException e){} }

public void Leave1() //注销事件 { String name=fromUserMessage.Name; Server.vectorStreamToUser.removeElementAt(Server.vectorUserList.indexOf(name)); Server.vectorUserList.removeElement(name); onlineNumber=\ Updating1(name); }

public void Updating1(String name)//更新用户列表 { try { if(onlineNumber.equals(\ { User toUserMessage=new User();

- 24 -

toUserMessage.Command=\ toUserMessage.Name=name;

toUserMessage.Message=\系统消息:大家欢迎\加入!!\ for(int i=1;i

newUserStream=(ObjectOutputStream)Server.vectorStreamToUser.elementAt(i-1); newUserStream.writeObject((User)toUserMessage); newUserStream.flush(); } } if(onlineNumber.equalsIgnoreCase(\ { User toUserMessage=new User(); toUserMessage.Command=\ toUserMessage.Name=name;

toUserMessage.Message=\系统消息:\走了!!!\ for(int i=0;i

newUserStream=(ObjectOutputStream)Server.vectorStreamToUser.elementAt(i); newUserStream.writeObject((User)toUserMessage); newUserStream.flush(); } } jLabel5.setText(\ \个客户\ jList1.setListData(Server.vectorUserList); onlineNumber=\ }

catch(IOException e){} }

public void Message1() //信息发送事件 { User toUserMessage=new User(); try {

toUserMessage.Message=fromUserMessage.Message; if(fromUserMessage.Command.equals(\ { for(int i=0;i

- 25 -

streamToUser=(ObjectOutputStream)Server.vectorStreamToUser.elementAt(i); streamToUser.writeObject((User)toUserMessage); streamToUser.flush(); } } }

if(fromUserMessage.Command.equals(\ { for(int i=0;i

catch(IOException e){} } } }

第四章 聊天室的调试

登录界面:

注册界面:

- 26 -

主界面:

服务器界面:

- 27 -

第五章 课程设计总结

5.1开发中遇到的问题

我在通讯录系统程序设计过程中,遇到的问题大体可分为两类:

A.知道但不会。这类问题往往是我知道应该怎么去设计,但却就是动不了手,要不就错误百出。

B.完全不会。这类问题摆在面前,我只能束手无策,苦恼而又无奈。

5.2问题分析与解决方法

对于第一类问题,其实本质上不存在什么大的问题,都是因为自己平时学习功底不够,还有编程时不够谨慎,才造成的。人非完人,学过了,有点不懂或迷惑的地方也是很正常的,再说竟然知道怎么做,有希望,那就有信心去解决。我在精神上坚定了,就能耐下性子征服它。通过查阅书本,仔佃分析、思考,请教同学、老师,这类问题还是得到了很好的解决。

对于第二类问题。造成的原因可分两种:一是明显的超过了我的能力范围;二是因为我对问题的认识、分析不够深入造成的假复杂现象。此类问题非要对症下药,效果方最好。如果没有找出原因而盲目努力,是不会有太大效果的。在这类问题出现后,人常常会感到烦躁、泄气,这时便不可能出现解决问题的可能。

怎么办好?我想,最重要的是要能稳住心态,相信自己终究会取得胜利的,同时也必须清楚地认识到自己的能力是有限的。此时,你需要学习知识,更要多借鉴他人在相同问题上的处理方法,弄懂了,一切就都好办了,离解决问题也就不会太远了。

5.3经验与教训

由于能力及时间的关系,这个Java聊天室程序没能达到其要求,很有点失望,很有点遗憾。在建立通信和连接数据库时,虽然很认真地在做,可总还是失败,这也导致了整个聊天室的无法运作(只有界面而已)。事实如此,不再赘言了。

这次Java实习,似乎量上过大,然而坚持做下来,还有很有意义和收获的。也许我的所得,对他人而言,可谓不值一提,但对我来说,它们的确让我在思想和能力上,更上了一层

- 28 -

楼。下面我就谈谈我的体会:

Jave与C语言编程相比,有着本质的不同.前者面向对象,即面向问题而设计程序,后者则是分析问题后,面向问题解决的过程而设计程序.本质的不同,导致程序设计的明显差异.Java设计的程序,通过划分类,通常都显得通俗易懂,条理清晰,而且很简捷.这是C语言所无法比拟的,除非它有很好的数据结构,但必须承认,就算如此,还是难以与之平行的.用Jave编聊天室,其实也不是那么复杂,但要是换用C语言,我真不知道其工作量有多大了。由此,我看到了Java的优越性,更坚定了我学好Java的决心.

用Java解决实际问题,分析问题是至关重要的。分析要合理、全面,只有这样,划分的类就不至于过大或过小。一个复杂的问题,就象这个聊天室吧,一开始不是什么都会做,先就完成简单、容易的,然后再带着小有的成就感,去征服难弄的部分。这种思想是处处适用的。

想说的,我已经说完了。最后再说一句:虽然目前我的编程能力很差劲,可我心中已有了目标,也许我走不到终点,但我一定会前进,绝不轻易放弃!梦想来之不易!

- 29 -

本文来源:https://www.bwwdw.com/article/g5la.html

Top