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.實驗截圖
先開啟服務端
再開啟客戶端
聊天過程
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。