面向对象课程设计--聊天室

一,团队介绍

团队成员职务负责部分博客链接
蔡佳生组长网络编程,多线程,数据库面向对象综合程序设计课程设计-CSDN博客
蔡朝辉组员客户端页面设计

二,项目git地址

蔡佳生1272752356/chat

三、项目功能架构图及主要功能流程图

四,项目重要代码

客户端

private static void Chat(String content,ClientFrame cframe) {
        System.out.println(content);
        String name=content.substring(0,content.indexOf("&"));
        String sender = content.substring(content.indexOf("&")+1, content.indexOf("/"));
        String word = content.substring(content.indexOf("/") + 1);
        //在聊天窗打印聊天信息
        cframe.jtaChat.append(cframe.sdf.format(new Date()) + " \n来自 " + name + ":" + word + " \n");
        //显示最新消息
        cframe.jtaChat.setCaretPosition(cframe.jtaChat.getDocument().getLength());
    }

    private static void OnlineListUpdate(String content,ClientFrame cframe) throws UnknownHostException {
        //提取在线列表的数据模型
        DefaultTableModel tbm = (DefaultTableModel) cframe.jtbOnline.getModel();
        //清除在线名单列表
        tbm.setRowCount(0);
        //更新在线名单
        String[] onlinelist = content.split(",");
        //逐一添加当前在线者
        for(String member : onlinelist)
        {
            String[] tmp = new String[3];
            //如果是自己则不在名单中显示
            if(member.substring(member.indexOf("&")+1).equals(InetAddress.getLocalHost().getHostAddress() + ":" + s.getLocalPort()))
            {tmp[0]=member.substring(0,member.indexOf("&"));Client.name=tmp[0];  continue;}
            tmp[0] = member.substring(0,member.indexOf("&"));
            tmp[1] = member.substring(member.indexOf("&")+1, member.indexOf(":"));
            tmp[2] = member.substring(member.indexOf(":") + 1);
            //添加当前在线者之一
            tbm.addRow(tmp);
        }
        //提取在线列表的渲染模型
        DefaultTableCellRenderer tbr = new DefaultTableCellRenderer();
        //表格数据居中显示
        tbr.setHorizontalAlignment(JLabel.CENTER);
        cframe.jtbOnline.setDefaultRenderer(Object.class, tbr);
    }

服务端

class ServerThread implements Runnable
{
    //获取的客户端Socket
    Socket s = null;
    //获取的服务器ServerSocket
    ServerSocket ss = null;
    //获取的客户端IP
    String ip = null;
    //获取的客户端端口
    int port = 0;
    //组合客户端的ip和端口字符串得到uid字符串
    String uid = null;

    String name=null;
    //name&ip:port

    //静态ArrayList存储所有uid,uid由ip和端口字符串拼接而成
    static ArrayList<String> uid_arr = new ArrayList<String>();
    //静态HashMap存储所有uid, ServerThread对象组成的对
    static HashMap<String, ServerThread> hm = new HashMap<String, ServerThread>();
    //放uid和name
    static HashMap<String,String> hm2=new HashMap<>();
    public ServerThread(Socket s, ServerSocket ss, String ip, int port)
    {
        this.s = s;
        this.ss = ss;
        this.ip = ip;
        this.port = port;
        uid = ip + ":" + port;
    }

    @Override
    public void run()
    {
        //将当前客户端uid存入ArrayList
        uid_arr.add(uid);
        //将当前uid和ServerThread对存入HashMap
        hm.put(uid, this);

        //时间显示格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");


        //控制台打印客户端IP和端口
        System.out.println("Client connected: " + uid);

        try
        {
            //获取输入流
            InputStream in = s.getInputStream();
            //获取输出流
            OutputStream out = s.getOutputStream();

           //向当前客户端传输连接成功信息
            String welcome = ip+":"+port;
            out.write(welcome.getBytes());



            //广播更新在线名单
            updateOnlineList(out);

            //准备缓冲区
            byte[] buf = new byte[1024];
            int len = 0;

            //持续监听并转发客户端消息
            while(true)
            {
                len = in.read(buf);
                String msg = new String(buf, 0, len);
                System.out.println(msg);
                //消息类型:退出或者聊天
                String type = msg.substring(0, msg.indexOf("/"));
                //消息本体:空或者聊天内容
                String content = msg.substring(msg.indexOf("/") + 1);
                //根据消息类型分别处理
                //客户端要退出
                if("Exit".equals(type))
                {
                    //更新ArrayList和HashMap, 删除退出的uid和线程
                    uid_arr.remove(uid_arr.indexOf(uid));
                    hm.remove(uid);
                    //广播更新在线名单
                    updateOnlineList(out);
                    //控制台打印客户端IP和端口
                    System.out.println("Client exited: " + uid);
                    //结束循环,结束该服务线程
                    break;
                }
                //客户端要聊天
                else if("Chat".equals(type))
                {
                    //提取收信者地址
                    String[] receiver_arr = content.substring(0, content.indexOf("/")).split(",");
                    //提取聊天内容
                    String word = content.substring(content.indexOf("/") + 1);
                    //向收信者广播发出聊天信息
                    chatOnlineList(out, uid, receiver_arr, word);
                } else if ("Name".equals(type)) {
                    String name=content.substring(0,content.indexOf("&"));
                    System.out.println("放进hm2的是:"+name);
                    hm2.put(uid,name);
                    updateOnlineList(out);

                } /*else if (type.equals("File")) {
                    BufferedInputStream bis=new BufferedInputStream(s.getInputStream());
                    BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("test\\Serverdir\\1.png"));
                    byte[] bytes=new byte[1024];

                    while((len=bis.read(bytes))!=-1){
                        bos.write(bytes,0,len);
                    }



                }*/

            }
        }
        catch(Exception e){}
    }

    //向所有已连接的客户端更新在线名单
    //OnlineListUpdate/192.168.125.15:60572,192.168.125.15:60583
    public void updateOnlineList(OutputStream out) throws Exception
    {
        for(String tmp_uid : uid_arr)
        {
            //获取广播收听者的输出流
            out = hm.get(tmp_uid).s.getOutputStream();
            //将当前在线名单以逗号为分割组合成长字符串一次传送
            StringBuilder sb = new StringBuilder("OnlineListUpdate/");
            for(String member : uid_arr)
            {   String name=hm2.get(member);
                sb.append(name+"&"+member);
                //以逗号分隔uid,除了最后一个
                if(uid_arr.indexOf(member) != uid_arr.size() - 1) {
                    sb.append(",");
                }
            }
            out.write(sb.toString().getBytes());
        }
    }

    //向指定的客户端发送聊天消息

    //Chat/192.168.125.15:60572/2
    public void chatOnlineList(OutputStream out, String uid, String[] receiver_arr, String word) throws Exception
    {
        for(String tmp_uid : receiver_arr)
        {
            //获取广播收听者的输出流
            out = hm.get(tmp_uid).s.getOutputStream();
            //发送聊天信息
            String name=hm2.get(uid);
            out.write(("Chat/" +name+"&"+ uid + "/" + word).getBytes());
        }
    }
}

五,项目运行截图

 

六、课程设计总结及展望

总结:深入学习了Java网络编程的相关知识,掌握了TCP协议的工作原理以及如何在Java中实现Socket通信。我们还学习了多线程编程,使聊天室能够同时处理多个客户端连接。在聊天室应用中,用户之间的交互是核心。设计易于使用且符合直觉的交互逻辑对于提升用户体验至关重要。你需要仔细思考消息如何发送、接收、展示以及如何让用户方便地进行这些操作。从设计和实现一个响应式用户界面到处理后端逻辑,再到优化网络通信,我们将获得宝贵的经验,并且在遇到困难和挑战时也会锻炼你的问题解决能力。总的来说,面向对象的程序设计会给您带来一个结构化、有条不紊的开发过程,同时也带来了不同层面的挑战。

展望:没有实现文件传输的功能。聊天室的功能比较简单,没有考虑用户界面的美观。在设计过程中,我们没有考虑到安全性问题,例如数据加密等。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
好的,我可以为您介绍一下面向对象程序设计中简单工厂模式的应用。 简单工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。该模式允许客户端通过传递类型参数来请求工厂创建所需类型的对象。 在一个简易计算器中,我们可以使用简单工厂模式来创建不同类型的运算对象。首先,我们需要定义一个运算接口,例如: ```java public interface Operation { double getResult(double numberA, double numberB); } ``` 然后,我们可以定义不同类型的运算类,例如: ```java public class AddOperation implements Operation { public double getResult(double numberA, double numberB) { return numberA + numberB; } } public class SubtractOperation implements Operation { public double getResult(double numberA, double numberB) { return numberA - numberB; } } public class MultiplyOperation implements Operation { public double getResult(double numberA, double numberB) { return numberA * numberB; } } public class DivideOperation implements Operation { public double getResult(double numberA, double numberB) { if (numberB == 0) { throw new IllegalArgumentException("除数不能为0"); } return numberA / numberB; } } ``` 最后,我们可以定义一个简单工厂类,根据传入的运算类型参数来创建相应的对象: ```java public class OperationFactory { public static Operation createOperation(String operationType) { Operation operation = null; switch (operationType) { case "+": operation = new AddOperation(); break; case "-": operation = new SubtractOperation(); break; case "*": operation = new MultiplyOperation(); break; case "/": operation = new DivideOperation(); break; default: throw new IllegalArgumentException("不支持的运算类型"); } return operation; } } ``` 使用简单工厂模式,我们可以在客户端代码中通过传递运算类型参数来获取相应的运算对象,例如: ```java public static void main(String[] args) { Operation operation = OperationFactory.createOperation("+"); double result = operation.getResult(3, 4); System.out.println(result); // 输出 7.0 } ``` 这样,我们就可以灵活地创建不同类型的运算对象,实现了代码的可扩展性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值