Java多线程实现多人聊天室功能
作者:CHANGEA-code
这篇文章主要为大家详细介绍了Java多线程实现多人聊天室功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文为大家分享了Java多线程实现多人聊天室功能的具体代码,供大家参考,具体内容如下
1.实验目的:
编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。
2.实验代码:
服务端程序代码:
ServerChar.java
package works; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; public class ServerChat { //定义Map集合用于存储用户的Socket以及用户的名字 key:Socket Value:用户名 public final static Map<Socket,String> socketsMaps = Collections.synchronizedMap(new HashMap<Socket,String>()); public static void main(String[] args) { // TODO Auto-generated method stub try { // 创建服务端套接字 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("------服务端暴露-------"); while (true) { // 监听客户端套接字,若有客户端连接,则代码不会往下执行,否则会堵塞在此处。 Socket socket = serverSocket.accept(); // 开启线程,用于读取客户端发送的信息,并转发给每一个客户端 new ThreadServer(socket).start(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } class ThreadServer extends Thread { private Socket socket; ThreadServer(){}; ThreadServer(Socket socket) { this.socket = socket; } @Override public void run() { try { while(true) { DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String data = dataInputStream.readUTF(); if(data.startsWith("①②③④")&&data.endsWith("①②③④")) { //发送过来的是用户名 //将Socket以及用户名字都存放在Map集合中 ServerChat.socketsMaps.put(socket, data.replace("①②③④","")); //获取所有的key(Socket),将所有用户的名字发送至客户端 Set<Socket> sockets = ServerChat.socketsMaps.keySet(); //获取所有的用户的名字,将这些名字拼装成一个字符串 Collection<String> names = ServerChat.socketsMaps.values(); StringBuffer sbf = new StringBuffer(); for(String userName :names) { sbf.append(userName).append(","); } System.out.println("sbf:"+sbf.toString()); for(Socket soc:sockets) { DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream()); dataOutputStream.writeUTF("①②③④"+sbf.toString()+"①②③④"); dataOutputStream.flush(); } } else{ //发送过来的是聊天信息 //获取所有的key(Socket),将所有用户的名字发送至客户端 Set<Socket> sockets = ServerChat.socketsMaps.keySet(); //將聊天信息广播出去 for(Socket soc:sockets) { DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream()); dataOutputStream.writeUTF("[ "+ServerChat.socketsMaps.get(socket)+" ]说:"+data); dataOutputStream.flush(); } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
客户端程序代码:
ClientChar.java
package works; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class ClientChat { private JFrame mainWin = new JFrame("聊天窗口"); // 消息展示框 private JTextArea displayTa = new JTextArea(14, 40); // 在线用户名称展示框 private DefaultListModel<String> userListModel = new DefaultListModel<>(); private JList<String> userList = new JList<>(userListModel); // 消息发送框 private JTextArea inputTF = new JTextArea(4, 40); // 消息按钮 private JButton sendBn = new JButton("发送"); // 用户记录当前聊天用户名 private String curUser; public static void main(String[] args) { new ClientChat().init(); } private void init() { try { // 通过弹出对话框获取用户输入的用户名 String userName = JOptionPane.showInputDialog(mainWin, "请输入您的用户名:"); // 把用户输入的用户名,赋给curUser curUser = userName; mainWin.setTitle(curUser + "的聊天窗口"); // 创建套接字 Socket socket = new Socket("192.168.193.1", 9999); // 向服务器声明 DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); //发送用户名到服务端 dataOutputStream.writeUTF("①②③④"+userName+"①②③④"); dataOutputStream.flush(); // 开启线程,用于读取服务器发送的信息 new ThreadClient(socket, this).start(); JPanel bottomPanel = new JPanel(); // 将消息框和按钮添加到窗口的底端 mainWin.add(bottomPanel, BorderLayout.SOUTH); bottomPanel.add(inputTF); bottomPanel.add(sendBn); ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 获取用户发送的消息 String message = inputTF.getText(); sendSms(message,socket); } }; // 给发送消息按钮绑定点击事件监听器 sendBn.addActionListener(listener); JPanel centerPanel = new JPanel(); // 将展示消息区centerPanel添加到窗口的中间 mainWin.add(centerPanel); // 让展示消息区可以滚动 centerPanel.add(new JScrollPane(displayTa)); displayTa.setEditable(false); // 用户列表和是否私聊放到窗口的最右边 Box rightBox = new Box(BoxLayout.Y_AXIS); userList.setFixedCellWidth(60); userList.setVisibleRowCount(13); rightBox.add(new JLabel("用户列表:")); rightBox.add(new JScrollPane(userList)); centerPanel.add(rightBox); // 关闭窗口退出当前程序 mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); // swing加上这句就可以拥有关闭窗口的功能 mainWin.setVisible(true); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } //点击发送后将消息发送到服务器 protected void sendSms(String sms, Socket socket) { try { //发送聊天消息到服务端 DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF(sms); dataOutputStream.flush(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } public DefaultListModel<String> getUserListModel() { return userListModel; } public JTextArea getDisplayTa() { return displayTa; } public JTextArea getInputTF() { return inputTF; } } // 定义线程类,用来读取服务器发送的信息 class ThreadClient extends Thread { private Socket socket; private ClientChat clientChat; ThreadClient() { } ThreadClient(Socket socket, ClientChat clientChat) { this.socket = socket; this.clientChat = clientChat; } @Override public void run() { try { while (true) { DataInputStream DataInputStream = new DataInputStream(socket.getInputStream()); String message = DataInputStream.readUTF(); if(message.startsWith("①②③④")&&message.endsWith("①②③④")) { //说明信息是用户名 String[] names = message.replace("①②③④","").split(","); // 将用户列表先清空 clientChat.getUserListModel().clear(); for (int i = 0; i < names.length; ++i) { clientChat.getUserListModel().addElement(names[i]); } } else { //说明是聊天信息,将聊天信息放在displayTa中 clientChat.getInputTF().setText(""); clientChat.getDisplayTa().append(message+"\t\n"); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3.实验截图
先开启服务端
再开启客户端
聊天过程
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。