java实训

时间:2024.5.2

实训报告

1 实训目的

以Java程序设计语言为基础,以Eclipse为开发平台,通过完成简易聊天程序的编写,调试,运行工作,进一步掌握Java应用程序的开发方法和编程技巧,巩固理论知识。

2 实训内容

系统的模块划分和各模块的功能介绍:

简易的多人聊天软件,支持任意两个客户端的私聊,所有客户之间的群聊,只需启动一个服务器端程序,允许多人上线聊天。该软件分为客户端(client)和服务端(server)两个模块,在一台计算机上启动服务器端程序,客户端使用用户名(昵称)登录,服务器端验证此昵称当前未使用准予登陆,否则其拒绝上线。用户上线后,在聊天界面,右下的下拉框选择聊天对象,可以是任意在线用户,也可以是所有人选择聊天。同时用户在服务器端的界面可以查看用户的上线、下线情况,所有用户的聊天记录。

3 详细设计与实现

3.1 服务器启动的实现

运行IMServerFrame类,出现服务器端启动界面窗口,如下图:

服务器启动界面截图

IMPanelClient类(JFrame)运行后,服务器启动,创建空的在线用户列表,创建服务器端ServerSocket,绑定6666端口,启动监听线ServerListenThread类,如果有用户发来连接请求立刻接受,判断接收客户传来的消息是不是“login”。如果是“login”,表示该用户想登陆,接续接收用户传来的消息,即 “用户名”。此时服务器端启动JDBCThread类查询当前用户列表,验证用户名是否已被使用。

1.为IMServerFrame类添加函数startServer(),如下:

public void startServer() throws IOException{

             ServerSocket server=new ServerSocket(6666,100);

             chatMeg.append("服务器程序已经启动…………"+'\n'); 

startServer.setEnabled(false);

             stopServer.setEnabled(true);

             userInfoList =new Vector();

             userNameList=new    Vector();

ServerListenThread listenThread=newServerListenThread(server,chatMeg,userInfoList,userNameList,userOnlineList);

          listenThread.start();

      }

2.为“启动服务”按钮添加点击事件,调用startServer()函数:

startServer.addActionListener(new ActionListener() {

                     public void actionPerformed(ActionEvent e) {

                            try {

                                   startServer();

                            } catch (Exception e1) {

                                   // TODO Auto-generated catch block

                                   e1.printStackTrace();

                            }

                     }

              });

              panel.add(startServer);

              startServer.setText("发送")

3.为ServerListenThread类添加函数startListen:

public void startListen(){

      while(!isStop&&!server.isClosed()){

             try{

                    SingleUserMegData clientData=new SingleUserMegData();

                    Socket socket=server.accept();

                    ObjectOutputStream       out=new ObjectOutputStream(socket.getOutputStream());

                           out.flush();

                    ObjectInputStream  in    =new ObjectInputStream(socket.getInputStream());

                    clientData.setSocket(socket);

                    clientData.setDataOut(out);

                    clientData.setDataIn(in);

String msg=(String)in.readObject();

                           if(msg.equals("Login")){

                                  String checkUserName=(String)in.readObject();

            JDBCThread       jt=new JDBCThread(chatMeg,userInfoList,userNameList,

     userOnlineList,clientData,checkUserName);

                          jt.start();

                           }  

                    }

                    catch(Exception e){

JOptionPane.showMessageDialog(null,"您已经关闭了侦听套接字!!!",

"系统警告",JOptionPane.ERROR_MESSAGE);

                    }

             }

      }

     为ServerListenThread类添加run函数如下,调用startListen方法,开始监听:

      public void run(){

             if(!server.isClosed()){

                    startListen();

             }

      }

}

3.2 用户远程登录的实现

用户a登陆时,向服务器发送“login” ,服务器端通过ServerListenThread类,判断接收客户传来的消息是不是“login”,如果是“login”,表示该用户想登陆,接续接收用户传来的消息,即 “用户名”。此时服务器端启动JDBCThread类查询当前用户列表,如果a已经在列表中,向客户端发送消息“fail”则不允许a登陆,如果a不在列表中,向该客户端发送消息”success”,允许登陆,并把a加入当前用户列表。

在client包下创建登陆窗口类UserLogin,登陆界面如图所示:

登陆的界面截图

1.在UserLogin的“登陆“按钮事件中添加代码

butLogin.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent arg0) {

                           String userName=userNameField.getText();

                           if(userName==null||userName.equals("")){

                                  JOptionPane.showMessageDialog(null,"昵称不能为空",

                                                "错误提示",JOptionPane.ERROR_MESSAGE);

                                  return;

                           }

                           try{

                                  Socket clientSocket=new Socket("127.0.0.1",5549);

                              ObjectInputStream     dataIn    =new ObjectInputStream(clientSocket.getInputStream());

                                  ObjectOutputStream  dataOut =new ObjectOutputStream(clientSocket.getOutputStream());

                                  boolean checkID=isLogin(dataIn,dataOut,userName);

                                  if(checkID){

                                         dispose();

                                         IMPanelClient client=new IMPanelClient(clientSocket,                                            dataIn,dataOut,userName);

                                         client.setVisible(true);

                            }   else{

JOptionPane.showMessageDialog(null,"此昵称以被使用,请换一个!","错误提示",JOptionPane.ERROR_MESSAGE);

                                  }

                    }  catch(Exception e){

                           JOptionPane.showMessageDialog(null,"服务器端没有响应",

                                                "错误提示",JOptionPane.ERROR_MESSAGE);

                           }

                    }

             });

2.为UserLogin类添加isLogin方法:

public boolean isLogin(ObjectInputStream dataIn,

                                            ObjectOutputStream dataOut,

                                            String userName){

             boolean checkResult=false;

             try{

dataOut.writeObject("Login");

                    dataOut.flush();

                    dataOut.writeObject(userName);

                    dataOut.flush();

                    String check=(String)dataIn.readObject();

                    if(check.equalsIgnoreCase("success")){

                           checkResult=true;

                    }   else

                           checkResult=false;

             }  catch(Exception e){

                    e.printStackTrace();

             }

             return checkResult;

      }

3.为JDBCThread类添加check方法,验证用户名和密码:

private void check(){

         try{

                if(!userNameList.contains(checkUserName)){

                       clientData.getDataOut().writeObject("success");

                       clientData.getDataOut().flush();

                       clientData.setUserName(checkUserName);

                       chatMeg.append(checkUserName+"上线了!"+"\n");

                       userInfoList.add(checkUserName);

                       userOnlineList.addItem(clientData);

                else{

                       clientData.getDataOut().writeObject("fail");

                       clientData.getDataOut().flush();

                }

         }  catch(Exception e){

                e.printStackTrace();

         }

  }

3.3  用户下线的实现

JDBCThread类在向用户发送允许登陆的success消息后,启动ServerReceiveThread线程,该线程用于服务器端与某一客户端收发消息(包括聊天消息,下线消息)。该线程通过megManage()方法判断,如果收到的消息表示当前是用户下线消息,从在线用户列表中删除此用户,反之收到的消息表示当前是用户发来的聊天信息,将此聊天信息转发给指定人。

public void megManage(){

              while(!isStop&&clientData.getSocket().isClosed()){

                     try{

                             String messageType=(String)clientData.getDataIn().readObject();

                            if(messageType.equalsIgnoreCase("用户下线")){

                                   String userName =(String)clientData.getUserName();

                                   chatMeg.append((userName+"下线了"+"\n"));

                                   userInfoList.remove(clientData);

                                   userNameList.remove(userName);

                                   userOnlineList.removeItem(clientData);

                     break;

                            }

                     }  catch(Exception e){

                            e.printStackTrace();

                            System.exit(0);

                     }

              }

       }

3.4  用户列表的发送

用户a登陆时,服务器端通过JDBCThread类查询当前用户列表,如果a已经在列表中,向客户端发送消息“fail”则不允许a登陆,如果a不在列表中,向该客户端发送消息”success”,允许登陆,并把a加入当前用户列表。

有用户登录时,向所有用户发送当前的在线用户列表,在JDBCThread类的check()函数中if (!userNameList.contains(checkUserName))中补充代码,如下:

String[] userArray=(String[])userNameList.toArray(new String[0]);

for(int i=0;i<userInfoList.size();i++){

      SingleUserMegData   clientData =(SingleUserMegData)userInfoList.get(i);

      clientData.getDataOut().writeObject("用户列表");

      clientData.getDataOut().flush();

      clientData.getDataOut().writeObject(userArray);

      clientData.getDataOut().flush();

}

用户下线时,在ServerReceiveThread类的megManage()方法中,向目前所有在线用户发送一份在线用户列表。

为IMPanelClient类添加窗口关闭事件,保证窗口关闭时,向服务器发送“用户下线“消息,并关闭和服务器端的连接:

addWindowListener(new WindowAdapter(){

                    public void windowClosing(WindowEvent e){

                           if(clientSocket!=null&&!clientSocket.isClosed()){

                                  try{

                                         dataOut.writeObject("用户下线");

                                         dataOut.flush();

                                         Thread.sleep(1000);

                                         clientSocket.close();

                                  } catch (Exception ex){

                                         ex.printStackTrace();

                                  }

                           }

                    }});

3.5   聊天的实现

当客户端的“发送”按钮或者文本框的回车事件中,向服务器端发送”聊天信息”+对方用户名+信息正文

服务器ServerReceiveThread类的 megManage()方法中添加一个判断,如果收到的消息以“聊天信息”开头,即认为是聊天信息,按照“对方用户名”找到相应的用户,将信息转发给他,如果“对方用户名”为“所有人”,则把这条消息转发给所有在线用户。

客户端ClientReceiveThread类的recevThread(),增加判断,如果收到的消息以“聊天信息”开头,则把此条信息显示在客户端界面上。

聊天消息格式:

    私聊时,客户端发送:“聊天信息”+对方用户名+信息正文

    群聊时,客户端发送:“聊天信息”+“所有人”+信息正文

服务端收到后转发:

    私聊,转发给指定人:“聊天信息”+ 发送方用户名 + 时间 + 信息正文

    群聊,转发给在线的所有人:“聊天信息”+发送方用户名+“群发” + 时间+信息正文。 聊天窗口如下:

聊天窗口的截图

1.客户端发送聊天信息的实现

为IMPanelClient类的“发送“按钮事件(或者文本框回车事件)添加下面代码:

ublic void actionPerformed(ActionEvent arg0) {

                    if(clientSocket!=null&&!clientSocket.isClosed()){

                           try{

                                  String message=textField.getText();

                                  String toSomebody=(String)onlineBox.getSelectedItem();

                                  dataOut.writeObject("聊天信息");

                                  dataOut.flush();

                                  dataOut.writeObject(toSomebody);

                                  dataOut.flush();

                                  dataOut.writeObject(message);

                                  dataOut.flush();

                                  java.util.Date d=new java.util.Date();

                                  SimpleDateFormat     s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                                  String dateStr=s.format(d);

receiveMeg.append(userName+" "+dateStr+"\n"+message+"\n");

                                  textField.setText("");

                                  }  catch(Exception e){   

                                  }

                           }

                    }

             });

2.服务器端接收聊天信息的实现

为ServerReceiveThread类的megManage方法添加下面代码(写在用户下线的if块结束后):

else if(messageType.equalsIgnoreCase("聊天信息")){

                    String toSomebody=(String)clientData.getDataIn().readObject();

                    String message=(String)clientData.getDataIn().readObject();

                    java.util.Date d=new java.util.Date();

                    SimpleDateFormat     s=new    SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                    String dateStr=s.format(d);

                    chatMeg.append(dateStr+"\n");

                    chatMeg.append(clientData.getUserName()+"对"+toSomebody+"说:"+message+"\n");

             if(toSomebody.equalsIgnoreCase("所有人")){

                    for(int i=0;i<userInfoList.size();i++){

SingleUserMegData toSomebodyData=(SingleUserMegData)userInfoList.get(i); if(toSomebodyData.getUserName().equals(clientData.getUserName())){

                                                       continue;

}    if(toSomebodyData.getSocket()!=null&&!toSomebodyData.getSocket().isClosed()){

                                  toSomebodyData.getDataOut().writeObject("聊天信息");

                                  toSomebodyData.getDataOut().flush();                                   toSomebodyData.getDataOut().writeObject(clientData.getUserName()+"群发:"+dateStr+"\n"+message+"\n");

                                  toSomebodyData.getDataOut().flush();

                                         }

                                  }

                           } else{

                                  int index=userNameList.indexOf(toSomebody);

      SingleUserMegDatatoSomebodyData=(SingleUserMegData)userInfoList.get(index);

                           if(toSomebodyData.getSocket()!=null

                                         &&toSomebodyData.getSocket().isClosed()){

                                  toSomebodyData.getDataOut().writeObject("聊天信息");

toSomebodyData.getDataOut().flush();

                              toSomebodyData.getDataOut().writeObject(

                              clientData.getUserName()+"  "+dateStr+

                                                              "\n"+message+"\n");

                              toSomebodyData.getDataOut().flush();

                                         }

                                  }

                           }

3.客户端接收聊天信息的实现

为ClientReceiveThread类的recevThread()方法添加判断,如果收到消息以“聊天信息开头“,把此信息显示在客户端窗口上:

 public void recevThread(){

             while(!isStop&&clientSocket!=null&&clientSocket.isClosed()){

                    try{

                           String megType=(String)dataIn.readObject();

                           if(megType.equalsIgnoreCase("用户列表")){

                                  String[] userList=(String[])dataIn.readObject();

                                  userOnlineList.removeAllItems();

                                  userOnlineList.addItem("所有人");

                                  for(int i=0;i<userList.length;i++){

                                         userOnlineList.addItem(userList[i]);

                                  }

                           } else if(megType.equalsIgnoreCase("聊天信息")){

                                         String message=(String)dataIn.readObject();

                                         receiveMeg.append(message); receiveMeg.setCaretPosition(receiveMeg.getDocument().getLength());

                           }

                    }catch(Exception e){

                           System.exit(0);

                    }

             }

      }

4 总结和心得

在开学的第一周,我们进行了为期一周的JAVA实训。现在结束了,回首上学期的java学习,重点还是在学习概念等一些常识性的东西,知道了JAVA语言的起源和发展,以及JAVA的特点,类及其方法,对象,数据类型,变量,包和接口,继承和多态,输入输出流,学会分析异常,抛出异常,后期主要是小程序运用,窗口界面设计和事件。我觉得这两种程序结构有很大的不同,不管是体系结构还是运行方式,都有很大的区别,我主要偏向于小程序的学习,因为感觉它用处比较大,可以做出好多好多好玩的游戏,运用程序等,且它灵活。呵呵,当然学知识可不能凭自己的爱好和一时兴趣,要一步一个脚印,认认真真,踏踏实实,理论与实践相结合,在扎实掌握课本实例和内容之后,有一定的扩展阅读和课外学习,充分全面的了解JAVA的应用和扩展运用。

在我所学的语言当中,我自认为JAVA是一门比较强大的面向对象的编程语言,不仅仅因为它的跨平台性,更多的是因为它的灵活多变和实用性较强,可以说比较的经典和强悍。

所以学好java语言有很大的用处,这次实训,面对一道陌生的代码和错误时,不应慌张和无措,首先应该想到这和课本上的哪些知识具有结合点,回忆和分析这种结构的算法和具体实施方法,综合考虑其他的方面。在编写时,我总是粗心大意把字母打错,不区分大小写,在报错后煞费苦心的去寻找那个小小的错瓦,所以,在编写JAVA代码时应该小心谨慎去输入哪怕是一个小小的符号,一个常量变量的设定,一个字母的大小写,这都无不考量着我们的细心和严谨,所以学习JAVA,不仅对我们以后学习其他语言有很大的好处,而且也让我们知道了和理解了作为一个编程人员首先应具有的良好心理素质,那就是冷静思考和专心致志。对待学术知识应该是严谨和认真。

这次实训,我们更多学到的是不懂就问和自己应该尽自己的全力去尝试,哪怕失败,只要自己尽自己的全力,和身边同学一起探讨而不是抄袭,团结合作,发挥团队意识,最后在自己的努力下,终于运行成功,这种成就感美不可言,心情愉悦至极。

最后终于要结束了,大家都有种释怀的感觉,当然我想我更多的是兴奋和自己掌握了知识之后的饱满感,学知识就像吃东西一样,吃饱了就应该好好的消化。要不断的温习和运用,做到举一反三,将所学知识充分融入到平时的学习生活中去,为以后的工作做好坚实的基础。感谢学校和老师能够为我们提供这次机会,让我们更好的掌握和了解JAVA这门语言。谢谢!

更多相关推荐:
java实训报告模板

辽宁建筑职业学院Java高级应用实训报告课题名称婚庆公司网站专业软件技术班级xxxxxxxxxx学号姓名xxxx指导教师xxx二O一三年十二月三十日成绩评定标准1目录一课程设计目的32二课程设计题目描述和要求3...

java软件培训实习报告

实习报告一、实习时间20xx.01.08--20xx.05.18二、实习地点无锡NIIT软件服务外包实训基地三、实习目的进一步了解Java开发的相关知识,掌握Java开发的基本技术,丰富Java开发的实战经验。…

java实习报告

设计地点:软件三机房专业:计算机网络技术指导教师:***班级:20XX级计网班设计:***设计时间:20XX.12.31-20XX.1.13目录第一章概论1第一节设计目的1第二节设计要求1第三节设计任务1第二章…

java实训报告模板

软件学院实训报告实训项目班级学号姓名上课时间教师签名实训报告详细内容包括一实训每日报告113一通过这节课我学到了1通过继承线程类Thread编写线程2通过实现Runnable接口来创建线程3使用静态方法slee...

java实习总结报告

java实习总结报告,内容附图。

Java项目实训报告模板

实训报告书课程:Java项目实训专业班级:学生姓名:学号:指导教师:完成日期:重庆电子工程职业学院软件学院目录目录................................................…

java实训报告

实训8接口与抽象类实训目的1理解接口与抽象类的思想2掌握接口与抽象类在Java中的语法规则和结论灵活运行进行编程实训案例通过编程验证如下结论1接口中的属性默认为static和final方法默认为abstract...

《Java程序开发实训》综合实训报告

Java程序开发实训综合实训报告题目姓名学号班级一系统实现的主要功能及运行结果截图二综合实训过程中遇到的问题及解决方法三本次综合实训中的收获及体会四对本课程教学的建议

java实训报告

烟台南山学院软件工程学院网络编程课程实训报告20xx20xx学年第1学期姓名朕学号888888专业软件技术班级软8指导教师白晓网络编程课程实训报告

Java实验报告

JAVA课程标准实验报告学号1040501211姓名陈嘉生江苏科技大学计算机科学与工程学院基础部1实验一流程控制语句一实验目的1234二实验内容1安装开发环境JDK2编写一个JAVA应用程序在输出窗口显示quo...

java超市管理系统实训报告

11课程设计的目的通过本次课程设计使学生能够全面深刻地掌握数据库系统的设计流程根据在数据库原理课程中所学到的数据库理论知识结合某个具体的实际需求最终开发出一个较为实用的数据库系统12课程设计的背景和意义121课...

java实训三实训报告

北京联合大学实验报告课程项目名称JAVA语言课程实验报告实验3学院自动化学院专业自动化班级学号姓名成绩20xx年4月4日一实验目的1掌握结构化程序设计的方法2学习用ifelse语句实现单分支3学习用ifelse...

java实训报告(33篇)