文章目录

  • 前言
  • 一、服务器端
    • 1.启动服务器端,打开服务器端窗口
    • 2.创建ServerSocket,循环监听客户端连接
    • 3.存储连接到服务器端的多个Socket(集合)
    • 4.接收客户端发送的信息(多线程)
    • 5.将接收到的消息转发给所有的客户端socket
  • 二、客户端
    • 1.登录和注册界面
    • 2.信息认证(数据库)
    • 3.创建客户端Socket连接服务器
    • 4.聊天界面
    • 5.发送聊天信息
    • 6.接收服务器的信息(线程)
  • 三、项目效果
  • 总结

前言

在之前的学习中,我们已经学完了JAVASE的基本内容:基础语法、面向对象、异常、常用类、集合、线程、GUI、JDBC、网络编程。对于之前章节的内容我们除了牢记于心之外还应在实际场合中灵活掌握它们的应用。利用多人聊天室项目,我们可以把之前学习的内容系统的串联起来,在实战中加深理解。


一、服务器端

1.启动服务器端,打开服务器端窗口

public class Sever {public static void main(String[] args) {SeverFrame mySever = new SeverFrame();mySever.createSeverFrame();try {ServerSocket mySeverSocket = new ServerSocket(5200);mySever.start(mySeverSocket);} catch (IOException e) {e.printStackTrace();}}
}public void createSeverFrame(){this.setSize(600,600);this.setTitle("这是我的多人聊天服务器");this.setIconImage(new ImageIcon("4.jpg").getImage());this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setLocationRelativeTo(null);this.setResizable(false);JPanel myMessagePanel=new JPanel();myChatArea=new JTextArea(30,40);JScrollPane myChatScroll=new JScrollPane(myChatArea);myMessagePanel.add(myChatScroll);this.add( myMessagePanel);this.addWindowFocusListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {try {clientSocket.close();dispose();} catch (IOException ioException) {ioException.printStackTrace();}}});this.setVisible(true);}

2.创建ServerSocket,循环监听客户端连接

public void start(ServerSocket mySeverSocket){while(true){try {clientSocket= mySeverSocket.accept();sockets.add(clientSocket);System.out.println("成功连接上了第"+(++count)+"个客户端");new SocketThread(clientSocket).start();} catch (IOException e) {e.printStackTrace();}}}

3.存储连接到服务器端的多个Socket(集合)

ArrayList<Socket>sockets=new ArrayList<>();
public void start(ServerSocket mySeverSocket){while(true){try {clientSocket= mySeverSocket.accept();sockets.add(clientSocket);System.out.println("成功连接上了第"+(++count)+"个客户端");new SocketThread(clientSocket).start();} catch (IOException e) {e.printStackTrace();}}}

4.接收客户端发送的信息(多线程)

   //用内部类的方式来为每个socket创建一个线程,一直循环监听class SocketThread extends Thread{Socket ClientSocket;DataOutputStream myOut;DataInputStream myIn;public SocketThread(Socket ClientSocket) {this.ClientSocket=ClientSocket;try {myOut=new DataOutputStream(ClientSocket.getOutputStream());} catch (IOException e) {e.printStackTrace();}try {myIn=new DataInputStream(ClientSocket.getInputStream());} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {while(true){try {String message= myIn.readUTF();myChatArea.append(message+"\n");//使用迭代器,给每个上线了的客户端都发送消息,把下线的客户端移出集合Iterator<Socket>it=sockets.iterator();while(it.hasNext()){Socket s=it.next();if(s.isClosed()){it.remove();continue;}DataOutputStream out=new DataOutputStream(s.getOutputStream());out.writeUTF(message);}} catch (IOException e) {stop();}}}}

5.将接收到的消息转发给所有的客户端socket

 //使用迭代器,给每个上线了的客户端都发送消息,把下线的客户端移出集合Iterator<Socket>it=sockets.iterator();while(it.hasNext()){Socket s=it.next();if(s.isClosed()){it.remove();continue;}DataOutputStream out=new DataOutputStream(s.getOutputStream());out.writeUTF(message);}

二、客户端

1.登录和注册界面

public class Client {public static void main(String[] args) {LoginFrame myLogin= new LoginFrame();myLogin.createLoginFrame();}
}public class LoginFrame extends JFrame {public void createLoginFrame() {this.setSize(400, 300);this.setTitle("这是我的多人聊天GUI");this.setIconImage(new ImageIcon("3.jpg").getImage());this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setLocationRelativeTo(null);this.setResizable(false);//添加面板JPanel total = new JPanel();   //总面板total.setLayout(new GridLayout(4, 1));//添加里面具体的面板JPanel loginPanel = new JPanel();JPanel accountPanel = new JPanel();JPanel passwordPanel = new JPanel();JPanel butPanel = new JPanel();//添加标签 文本框 密码框 按钮组件JLabel loginLabel = new JLabel("欢迎来到多人聊天室");loginLabel.setFont(new Font("宋体", Font.BOLD, 20));loginPanel.add(loginLabel);JLabel accountLabel = new JLabel("用户名");JTextField accountFiedl = new JTextField(15);accountPanel.add(accountLabel);accountPanel.add(accountFiedl);JLabel passwordLabel = new JLabel("密 码");JPasswordField passwrodField = new JPasswordField(15);passwordPanel.add(passwordLabel);passwordPanel.add(passwrodField);JButton loginButton = new JButton("登录");JButton registerButton = new JButton("注册");butPanel.add(loginButton);butPanel.add(registerButton);//把所有的组件都加到总面板上去total.add(loginPanel);total.add(accountPanel);total.add(passwordPanel);total.add(butPanel);this.add(total);this.setVisible(true);loginButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {  判断用户名和密码的程序,判断成功后进入登录界面String account = accountFiedl.getText();String password = passwrodField.getText();if (account.equals("") || password.equals("")) {JOptionPane.showMessageDialog(null, "账号或者密码不能为空", "错误", JOptionPane.ERROR_MESSAGE);return;}try {LoginDao logindao = new LoginDao();int result = logindao.test(account, password);if (result == 0) {JOptionPane.showMessageDialog(null, "账号或者密码错误", "错误", JOptionPane.ERROR_MESSAGE);return;}} catch (Exception t) {t.printStackTrace();}try {Socket mySocket = new Socket("192.168.43.39", 5200);System.out.println("连接成功");ChatFrame myChatFrame = new ChatFrame(mySocket, accountFiedl.getText());dispose();myChatFrame.createChatFrame();} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "服务器连接失败", "错误", JOptionPane.ERROR_MESSAGE);}}});registerButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {dispose();RegisterFrame myRegisterFrame = new RegisterFrame();myRegisterFrame.createRegisterFrame();}});}
}public class RegisterFrame extends JFrame {public void createRegisterFrame() {this.setSize(400, 300);this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);this.setTitle("注册界面");this.setLocationRelativeTo(null);this.setLayout(new BorderLayout());this.setResizable(false);JLabel loginLabel = new JLabel("欢迎来到注册界面");loginLabel.setFont(new Font("宋体", Font.BOLD, 20));JPanel registerPanel = new JPanel();registerPanel.setLayout(new GridLayout(4, 1));JLabel account = new JLabel("用户名");JLabel password = new JLabel("密 码");JTextField accountfield = new JTextField(13);JTextField passwordfield = new JTextField(13);JButton but = new JButton("保存");JPanel labelPanel = new JPanel();labelPanel.add(loginLabel);JPanel accountPanel = new JPanel();accountPanel.add(account);accountPanel.add(accountfield);JPanel passwordPanel = new JPanel();passwordPanel.add(password);passwordPanel.add(passwordfield);JPanel buttonPanel = new JPanel();buttonPanel.add(but);registerPanel.add(labelPanel);registerPanel.add(accountPanel);registerPanel.add(passwordPanel);registerPanel.add(buttonPanel);this.add(registerPanel);but.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String account = accountfield.getText();String password = passwordfield.getText();if (account.equals("") || password.equals("")) {  //判断是否为空,空就提示用户重新输入JOptionPane.showMessageDialog(null, "请输入完整信息", "提示", JOptionPane.QUESTION_MESSAGE);return;}//这里可以加个验证,验证账号是否在数据库中存在try {RegisterDao dao= new RegisterDao();int result=dao.save(account,password);if(result!=1){dispose();new LoginFrame().createLoginFrame();}} catch (Exception exception) {exception.printStackTrace();JOptionPane.showMessageDialog(null, "程序有误", "提示", JOptionPane.QUESTION_MESSAGE);}}});this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {int choice = JOptionPane.showConfirmDialog(null, "您确定要关闭吗", "提示", JOptionPane.YES_NO_CANCEL_OPTION);{if (choice == 0) {dispose();new LoginFrame().createLoginFrame();}}}});this.setVisible(true);}
}

2.信息认证(数据库)


public class LoginDao {int result;public int test(String account, String password) throws ClassNotFoundException, SQLException {Connection con = null;Statement st = null;try {Class.forName("com.mysql.cj.jdbc.Driver");  // 1.注册JDBC驱动程序 :这需要初始化驱动程序,这样就可以打开与数据库的通信信道。String user = "jdbc:mysql://localhost:3306/chat_db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";String userName1 = "root";String password1 = "0521";con = DriverManager.getConnection(user, userName1, password1);PreparedStatement pst1 = con.prepareStatement(" SELECT COUNT(*)count1 FROM t_user WHERE account=? AND PASSWORD=?");pst1.setString(1, account);pst1.setString(2, password);ResultSet res = pst1.executeQuery();if (res.next()) {result = res.getInt("count1");}} finally {if (st != null) {st.close();}if (con != null) {con.close();}}return result;}
}public class RegisterDao {//dao包的含义:data access object 数据处理包public int save(String account, String password) throws ClassNotFoundException, SQLException {int result = 0;Connection con = null;Statement st = null;PreparedStatement pst1 = null;PreparedStatement pst2 = null;try {Class.forName("com.mysql.cj.jdbc.Driver");  // 1.注册JDBC驱动程序 :这需要初始化驱动程序,这样就可以打开与数据库的通信信道。String user = "jdbc:mysql://localhost:3306/chat_db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";String userName1 = "root";String password1 = "0521";con = DriverManager.getConnection(user, userName1, password1);//先验证账号在数据库中存在不存在,如果存在直接返回pst1 = con.prepareStatement("SELECT COUNT(*)count1 FROM t_user WHERE account=?");pst1.setString(1, account);ResultSet res = pst1.executeQuery();if (res.next()) {result = res.getInt("count1");}if (result != 0) {  //如果已经有账号存在,直接用return返回 返回1表示账号已经存在,返回0表示成功注册JOptionPane.showMessageDialog(null, "账号已经存在", "提示", JOptionPane.QUESTION_MESSAGE);return 1;}pst2 = con.prepareStatement("INSERT INTO t_user(account,password,reg_time)values (?,?,?)");pst2.setString(1, account);pst2.setString(2, password);pst2.setObject(3, new Date());pst2.executeUpdate();JOptionPane.showMessageDialog(null, "注册成功", "提示", JOptionPane.QUESTION_MESSAGE);}    finally {if (st != null) {st.close();}if (con != null) {con.close();}if (pst1 != null) {pst1.close();}if (pst2 != null) {pst2.close();}}return 0;}
}

3.创建客户端Socket连接服务器

               try {Socket mySocket = new Socket("192.168.43.39", 5200);System.out.println("连接成功");ChatFrame myChatFrame = new ChatFrame(mySocket, accountFiedl.getText());dispose();myChatFrame.createChatFrame();} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "服务器连接失败", "错误", JOptionPane.ERROR_MESSAGE);}

4.聊天界面

public void createChatFrame() {this.setSize(600, 600);this.setTitle("您好" + account + "欢迎回来");this.setIconImage(new ImageIcon("3.jpg").getImage());this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);this.setLocationRelativeTo(null);this.setResizable(false);this.setLayout(new BorderLayout());JPanel myTotalPanel = new JPanel();JPanel myMessagePanel = new JPanel();myChatArea = new JTextArea(30, 40);JScrollPane myChatScroll = new JScrollPane(myChatArea);myMessagePanel.add(myChatScroll);JPanel mySendPanel = new JPanel();JTextField mySendText = new JTextField(15);mySendText.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == 10) {if (mySendText.getText().length() != 0) {String message = account + " " + new Date().toLocaleString() + "\n" + mySendText.getText();try {myOut.writeUTF(message);mySendText.setText("");} catch (IOException ioException) {ioException.printStackTrace();}} else {JOptionPane.showMessageDialog(null, "聊天内容不能为空", "错误", JOptionPane.ERROR_MESSAGE);}}}});JButton mySendButton = new JButton("发送");mySendButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (mySendText.getText().length() != 0) {String message = account + " " + new Date().toLocaleString() + "\n" + mySendText.getText();try {myOut.writeUTF(message);mySendText.setText("");} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "服务器连接失败", "错误", JOptionPane.ERROR_MESSAGE);}} else {JOptionPane.showMessageDialog(null, "聊天内容不能为空", "错误", JOptionPane.ERROR_MESSAGE);}}});this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {int choice = JOptionPane.showConfirmDialog(null, "您确定要关闭吗", "提示", JOptionPane.YES_NO_CANCEL_OPTION);{if (choice == 0) {dispose();}}}});mySendPanel.add(mySendText);mySendPanel.add(mySendButton);myTotalPanel.add(myMessagePanel, BorderLayout.CENTER);myTotalPanel.add(mySendPanel, BorderLayout.SOUTH);this.add(myTotalPanel);this.setVisible(true);}

5.发送聊天信息

        JButton mySendButton = new JButton("发送");mySendButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (mySendText.getText().length() != 0) {String message = account + " " + new Date().toLocaleString() + "\n" + mySendText.getText();try {myOut.writeUTF(message);mySendText.setText("");} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "服务器连接失败", "错误", JOptionPane.ERROR_MESSAGE);}} else {JOptionPane.showMessageDialog(null, "聊天内容不能为空", "错误", JOptionPane.ERROR_MESSAGE);}}});

6.接收服务器的信息(线程)

   public ChatFrame(Socket mySocket, String account) throws IOException {this.mySocket = mySocket;myOut = new DataOutputStream(mySocket.getOutputStream());myIn = new DataInputStream(mySocket.getInputStream());this.account = account;new SocketThread().start();}class SocketThread extends Thread {@Overridepublic void run() {boolean flag = true;while (flag) {try {String str = myIn.readUTF();myChatArea.append(str + "\n" + "\n");} catch (IOException e) {e.printStackTrace();flag = false;JOptionPane.showMessageDialog(null, "服务器连接失败", "错误", JOptionPane.ERROR_MESSAGE);}}}}

三、项目效果





总结

多人聊天室项目涵盖了JAVASE的大部分内容:基础语法、集合、线程、JDBC等。JAVASE是JAVA的基础内容部分,树高千丈,根源还是在底部,想要在JAVA后续的学习中学的轻松牢固,基础内容尤为重要。我们不仅要学会各个章节的基本概念,还要在实战中掌握它们的实际应用,多上手操练代码,我们的技术才能发展更快更远。


JAVASE多人聊天室项目实战相关推荐

  1. 基于socket实现的多人聊天室项目(python)

    最近做了一个多人聊天室项目,主要目的是练习和巩固socket编程. 在开始之前,可以先了解一下socket的TCP三次握手和四次挥手. 参考:https://blog.csdn.net/luoyoub ...

  2. 基于SpringBoot的websocket的多人聊天室项目

    文章目录 1.websocket 什么是websocket? 使用步骤 1.引入依赖 2.建立配置类 3.业务层 Web类 HTML 遇到的问题 项目github地址 1.websocket 什么是w ...

  3. 基于python面向对象多人聊天室

    基于python面向对象多人聊天室 1.项目环境 项目名称:多人聊天室 项目模式:C/S 开发环境:win10+python3.8+pycharm 所需知识:python GUI编程,多线程编程,网络 ...

  4. 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一.UDP的概念 1.1 UDP 1.2 UDP特点 二. 采用UDP实现多人聊天室原因 三.多人聊天室项目功能 四.实现多人聊天室项目流程分析 4.1 前期准备 4.1.1 定义结构体 4 ...

  5. 视频教程-实战Go语言:多人聊天室-Go语言

    实战Go语言:多人聊天室 多年互联网从业经验: 有丰富的的企业网站.手游.APP开发经验: 曾担任上海益盟软件技术股份有限公司项目经理及产品经理: 参与项目有益盟私募工厂.睿妙影音家庭物联网设备.手游 ...

  6. 实战Go语言:多人聊天室-欧阳桫-专题视频课程

    实战Go语言:多人聊天室-77人已学习 课程介绍         ·基于Go的网络和并发技术开发多人在线聊天室: ·功能包括:单聊.群聊.昵称.上下线通知.聊天日志等: ·技术栈:TCP通信.协程并发 ...

  7. Go语言实战:多人聊天室V2.0-欧阳桫-专题视频课程

    Go语言实战:多人聊天室V2.0-117人已学习 课程介绍         1.0版本基于Go语言的TCP通信实现了基本聊天功能: 2.0版本实现群聊系列功能,包括:建群.申请加群.群主审核.查看群信 ...

  8. NIO网络编程实战之简单多人聊天室

    NIO网络编程实战 利用NIO编程知识,实现多人聊天室. 1. NIO编程实现步骤 第一步:创建Selector 第二步:创建ServerSocketChannel,并绑定监听端口 第三步:将Chan ...

  9. 【linux项目】多人聊天室

    多人聊天室 搭建一个可以实现多个用户同时在线聊天的多人聊天室 客户端 1.注册用户信息 bool Register()89 {90 if(!connect_server())91 {92 return ...

最新文章

  1. 【翻译】HTML5开发——轻量级JSON存储解决方案Lawnchair.js
  2. Openlayers4中实现动态线效果
  3. admin——django自带数据库管理工具
  4. 第一章 计算机网络 1 计网体系结构的概念和功能 [计算机网络笔记]
  5. MySQL双主如何解决主键冲突问题
  6. Linux设备驱动01:Linux设备驱动概述
  7. [短线是银]条件选股公式集源码!
  8. 记忆减退之----LM1117 电路连接图
  9. Pascal小游戏 俄罗斯方块怀旧版
  10. 2017-2018-1 20155228 《信息安全系统设计基础》第三周学习总结
  11. BUUCTF·[AFCTF2018]Vigenère·WP
  12. UiPress – 现代WordPress仪表板主题
  13. A Personality traits and job candidate screening via analyzing facial videos 阅读笔记
  14. 使用 mysql_use_result 还是使用 mysql_store_result
  15. HIVE自定义UDF函数-经纬度转换成省市地址
  16. 2021年江西省安全员C证考试题及江西省安全员C证免费试题
  17. Bartender 4怎么用?Bartender 4 mac使用教程
  18. 【让我们为你连接到网络】未识别的网络进行修复
  19. 解题报告 (十四) 数位DP
  20. HttpClient-v4.5官方文档翻译

热门文章

  1. 侯捷的c++教程(1)
  2. 利用鸿鹄优化共享储能的SCADA 系统功能,赋能用户数据自助分析
  3. [转]创业时如何选择合作伙伴
  4. 科大讯飞语音iOS版
  5. 账龄分析Vintage
  6. word关闭未响应_用word保存出高清的pdf文件
  7. Visio “文件” 未响应
  8. 神经网络 pytorch 分类二维矩阵图像和一维向量的方法
  9. 安卓逆向基础视频链接大全
  10. linux c语言sleep的时间实验