Java聊天室项目GUI界面化实现(Java聊天室 IO流 Socket流 GUI界面 )

Java聊天室项目GUI界面化实现(Java聊天室 IO流 Socket流 GUI界面 )

文章目录

1.Java聊天室 IO流 Socket流 GUI界面 服务端功能及页面介绍
2.Java聊天室 IO流 Socket流 GUI界面 客户端功能及页面介绍
3.Java聊天室 IO流 Socket流 GUI界面 工具类Utils代码及解释(FileUtils文件发送的工具类Utils PathUtils是设置背景图片的图片路径Utils工具类
4.Java聊天室 IO流 Socket流 GUI界面 枚举与包装消息内容代码及详解User里存放的是将需要传递的内容整体打包为一个对象 然后分开读取 Net里存放的是服务端的消息类型枚举
5.Java聊天室 IO流 Socket流 GUI界面 服务端主界面代码及功能详解
6.Java聊天室 IO流 Socket流 GUI界面 服务端的RegisterUserThread线程与ServerReadMsgThread消息读取线程
7.Java聊天室 IO流 Socket流 GUI界面 客户端MainView界面详解
8.Java聊天室 IO流 Socket流 GUI界面 客户端RegisterView界面详解
9.Java聊天室 IO流 Socket流 GUI界面 客户端FunctionView界面详解
10.Java聊天室 IO流 Socket流 GUI界面 客户端ClientReadMsgThread消息读取进程详解
11.Java聊天室 IO流 Socket流 GUI界面 客户端TiShi界面详解
12.Java聊天室 IO流 Socket流 GUI界面 客户端DeleteCompoent界面详解
13.Java聊天室 IO流 Socket流 GUI界面 客户端下线功能
14.Java聊天室 IO流 Socket流 GUI界面 客户端ChaXunCompoent界面详解
15.Java聊天室 IO流 Socket流 GUI界面 客户端YinShenCompoent界面详解
16.Java聊天室 IO流 Socket流 GUI界面 客户端WenJianconpoent界面详解
17.Java聊天室 IO流 Socket流 GUI界面 客户端PublicCompoent界面详解
18.Java聊天室 IO流 Socket流 GUI界面 客户端UserManageCompoent界面详解
19.Java聊天室 IO流 Socket流 GUI界面 客户端ShangXiaCompoent界面详解
20.Java聊天室 IO流 Socket流 GUI界面 客户端PrivateCompoent界面详解
21.Java聊天室 IO流 Socket流 GUI界面 所有的效果图
22.Java聊天室 IO流 Socket流 GUI界面 所有的代码
23.总结与bug
  • 在使用objectstream流的时候 记得要定义种子 并且 in与out流的创建不能同时创建多个 否则会报找不到上次读取后的位置
  • 切换账号功能有问题 第二次登陆新的账号 新的流无法创建出来 所有的功能都会出现问题 有待改正 这一问题
  • 其他功能有些没有添加校验 后续可以将用户名查找进行添加 判断此用户名是否可以进行聊天与文件等的发送
  • 有待改进与完善

SANWA聊天室主体页面分布

  • 布局


  • 分为服务端与客户端分别进行构建

聊天室需求与思路

  • 需求
必须完成的功能点:
1、用户名登录注册(判断有没有重复用户名,可设置ip和端口)
2、上下线提醒
3、在线列表
4、私聊
5、公聊
6、发送文字,文件。
7、聊天记录 保存 查询 删除。
8、下线

选做功能
2、建群
3、大文件传输。(新建流传输)*
4、离线消息*
5、个人信息设置
6、语音聊天*
7、朋友圈
8、文字表情
9、增删好友,修改好友备注名。
  • 思路
1:分别开发客户端 和 服务端  先实现客户端和服务的聊天功能
2.我们要把客户端和服务端 读消息和写消息 不能都放主线程 这样设计不合理
我们主线程 应该录入消息  子线程用来读取消息 
以后开发中要注意 键盘录入数据应该放在主线程 ,如果放在子线程 有可能录入不了数据

3.在实际中 我们肯定是不和服务器聊天的,我们是客户端和客户端进行聊天 ,所以我们修改代码
服务器 只读取消息 然后转发消息 

那实现步骤 我们循环监听客户端 每连接一个客户端 我们把 管道存到一个集合中 并循环开启一个客户端 对应的读取消息的子线程 并把管道集合传过去
子线程拿到 相应的管道 获取该管道的输出流 写出去 当然这里需要我们定义 消息格式 比如: 接收者:消息内容:发送者

4.上步我们用的是List单列集合,通过索引来区分的每个用户,不是很方便,我们改进一下,我们可以用双列集合来,保存一个用户名和他对应的管道,在服务端通过
键找值的方式来获取对应管道,进行消息的转发,
这样需要我们在 客户端 在开启聊天线程之前,先进行用户名的注册, 服务端也不要着急 开启 聊天线程,  而是再创建一个保存用户名的线程,单独完成用户名的注册
用户名注册完成后,在保存用户名的线程里面 来开启 服务端的聊天线程

5. 上步用户名完成后,我们顺遍在保存用户名的线程里面 ,再把上线提醒功能做了

6. 在客户端里面 开启聊天线程之后  在提供 菜单选项,让用户选择 私聊,公聊,在线列表,退出等 选项

7.在实现私聊功能时 约定发送消息的格式为  接收者:消息内容:消息类型

8.服务端 收到客户端发来的消息后,拆分消息,根据消息类型 进行不同的逻辑处, 将消息转发回去 转发格式 约定为  发送者:内容:消息类型:时间

  • 12
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Dimension ss = Toolkit.getDefaultToolkit().getScreenSize(); public ChatClient(){ super("登录聊天室"); pnlLogin = new JPanel(); this.getContentPane().add(pnlLogin); lblServer = new JLabel("服务器:"); lblPort = new JLabel("端口:"); lblName = new JLabel("用户名:"); lblPassword = new JLabel("口 令:"); tfServer = new JTextField(15); tfServer.setText("127.0.0.1"); tfPort = new JTextField(6); tfPort.setText("8000"); tfName = new JTextField(20); pwd = new JPasswordField(20); btnLogin = new JButton("登录"); btnRegister = new JButton("注册"); btnExit=new JButton("退"); pnlLogin.setLayout(null); pnlLogin.setBackground(new Color(205,112,159)); lblServer.setBounds(40,35,50,30); tfServer.setBounds(90,35,102,25); lblPort.setBounds(195,35,35,30); tfPort.setBounds(230,35,55,25); lblName.setBounds(40,70,50,30); tfName.setBounds(90,70,195,25); lblPassword.setBounds(40,100,50,30); pwd.setBounds(90,100,195,25); btnLogin.setBounds(30,160,70,25); btnRegister.setBounds(130,160,70,25); btnExit.setBounds(230,160,70,25); pnlLogin.add(lblServer); pnlLogin.add(tfServer); pnlLogin.add(lblPort); pnlLogin.add(tfPort); pnlLogin.add(lblName); pnlLogin.add(tfName); pnlLogin.add(lblPassword); pnlLogin.add(pwd); pnlLogin.add(btnLogin); pnlLogin.add(btnRegister); pnlLogin.add(btnExit); //设置登录窗口 setResizable(false); setSize(320,260); setVisible(true); setLocation((ss.width-getWidth())/2,(ss.height-getHeight())/2); //为按钮注册监听 btnLogin.addActionListener(this); btnRegister.addActionListener(this); btnExit.addActionListener(this); addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); } //按钮监听响应 public void actionPerformed(ActionEvent ae){ Object source = ae.getSource(); if (source.equals(btnLogin)){ if (tfName.getText().equals("") || pwd.getPassword().equals("")) JOptionPane.showMessageDialog(null, "用户名或密码不能为空"); else strServerIp = tfServer.getText(); login(); } if (source.equals(btnRegister)){ strServerIp = tfServer.getText(); this.dispose(); new Register(strServerIp,8000); } if (source == btnExit) { System.exit(0); } } public void login() { User data = new User(); data.name = tfName.getText(); data.password = new String(pwd.getPassword()); try { String str = InetAddress.getLocalHost().toString(); data.ip = " "+ str.substring(str.lastIndexOf("/"), str.length()); } catch (UnknownHostException ex) { Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex); } try{ Socket sock = new Socket(strServerIp,8000); ObjectOutputStream os = new ObjectOutputStream(sock.getOutputStream()); os.writeObject((User) data); //读来自服务器socket的登录状态 BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream())); String status = br.readLine(); if (status.equals("登陆成功")){ new ChatRoom((String)data.name,strServerIp); this.dispose(); //关闭对象 os.close(); br.close(); sock.close(); } else{ JOptionPane.showMessageDialog(null, status); os.close(); br.close(); sock.close(); } } catch (ConnectException e1){ JOptionPane.showMessageDialog(null, "连接到制定服务器失败!"); } catch (InvalidClassException e2) { JOptionPane.showMessageDialog(null, "类错误!"); } catch (NotSerializableException e3) { JOptionPane.showMessageDialog(null, "对象未序列!"); } catch (IOException e4) { JOptionPane.showMessageDialog(null, "不能写入到指定服务器!"); } } public static void main(String arg[]){ new ChatClient(); } }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值