【Java socket编程】多人聊天室

这篇具有很好参考价值的文章主要介绍了【Java socket编程】多人聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

课程设计大作业

功能:

1.具有点对点通信功能,任意客户端之间能够发送消息。

2.具有群组通信功能:

  1. 客户端可以自主建立群组,添加或删除组成员;
  2. 客户端能够向组内成员同时发送消息,其他组成员不能收到。

3.具有广播功能

  1. 客户端能够向所有其他成员广播消息
  2. 服务器可以向所以客户端广播系统消息

4.其他功能

  1. 服务器
    1. 可以强制下线用户
    2. 根据客户端上线下线情况,实时刷新在线用户列表
  2. 客户端
    1. 登录:登录时只有账号密码合法才能登录成功,进入聊天界面。若该用户未注册过,则使用其输入的账户和密码为其注册,下次使用该密码进行审核。
    2. 实时刷新用户列表:客户端的上线下线能够在其他客户端上面实时刷新。
    3. 切换聊天对象:用户切换聊天对象时在同一个界面之间进行切换,切换不同聊天对象时,聊天记录不会消失。
    4. 消息提示:当接收到新消息,且发送方不是当前的聊天对象时,会点亮该发送方,提醒用户。当用户点击该好友进行聊天时,会取消点亮。
    5. 加密与解密:对消息进行了简单的加密保护。

为了界面较为美观且代码简洁,使用了Swing UI designer进行界面设计。

java多人聊天室,java,开发语言,网络协议,websocket

 

登录界面

java多人聊天室,java,开发语言,网络协议,websocket

客户端界面

java多人聊天室,java,开发语言,网络协议,websocket

 

服务器界面

java多人聊天室,java,开发语言,网络协议,websocket

 

java多人聊天室,java,开发语言,网络协议,websocket 

 

主要数据结构

服务器Server

在线用户——clients——Map<String, DataOutputStream>

在线用户列表——onlineClient——List<String>

用户列表——userList——Jlist

系统消息记录——sysMessageList——Jlist

组群+成员——groups——Map<String, List<String>>

客户端Client

当前聊天对象——receiver——String

在线用户——onlineUser——List<String>

好友列表——friendList——JList

所属组群——groups——List<String>

当前界面消息记录——message_List——JList

高亮好友列表——highlightFrined——Set<String>

聊天记录——chatRecord——Map<String, DefaultListModel>

 

主要成员函数

服务器Server

  1. start(): 服务器启动函数,创建服务器套接字,接受来自客户端的连接请求,并为每个新的客户端创建一个新线程(ClientHandler)来处理该客户端的消息。
  2. ClientHandler: 内部类,负责处理每个客户端的请求。其主要成员函数包括:
    1. run(): 持续读取客户端的消息,根据消息类型执行不同的操作,如:用户上线(1111),广播消息(2333),私聊消息(1333),创建小组(5555),添加小组成员(6666),移除小组成员(7777),小组消息(8888)等。
    2. broadcast(): 向所有在线用户广播消息,用于广播和发送系统消息。
    3. broadcastToGroup(): 向某个小组的所有成员广播消息,用于处理组群聊。
    4. sendTo(): 向特定用户发送消息,用于处理私聊。
    5. sendOnlineList(): 发送当前在线用户列表到特定用户,用于刷新用户列表。
  3. refresh_message(): 服务器发送系统消息给所有在线用户或群聊。
  4. forceDisconnect(): 服务器强制某个用户下线。
  5. broadcast(): 向所有在线用户广播消息。
  6. encryptWrite(): 将发送的消息进行简单的加密并写入输出流。
  7. readDecrypt(): 从输入流中读取并解密消息。
  8. nowDate(): 返回当前的日期和时间。

客户端Client

  1. init(): 用于初始化界面和各个组件的事件监听器。
  2. refresh_message(): 用于发送消息并刷新消息列表。
  3. run(): 是程序的运行逻辑。首先创建并显示聊天窗口的界面。然后,创建一个新的线程用于每秒钟更新聊天记录或好友列表。接下来,创建一个新的线程来处理与服务器的通信。
  4. HighlightedListCellRenderer: 用于自定义好友列表的渲染器,达到点亮好友的效果。
  5. encryptWrite(): 将发送的消息进行简单的加密并写入输出流。
  6. readDecrypt(): 从输入流中读取并解密消息。
  7. nowDate(): 返回当前的日期和时间。

登录窗口Login

  1. Login(): 构造函数,加载账户信息,添加监听器。
  2. login():检查账户是否存在以及密码是否正确。
  3. loadAccounts(): 从指定文本文件中加载账户信息。
  4. saveAccounts(): 把所有的账户信息保存到指定文本文件中。

PS:由于使用了Swing UI designer进行界面设计,源代码中没有主要的UI设计代码,需要下载整个文件才能成功运行。

服务器源代码

package Chat;

import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.time.LocalDateTime;

public class Server {
    private int port = 5000;
    private ServerSocket serverSocket = null;

    private Map<String, DataOutputStream> clients = new HashMap<>();
    private List<String> onlineClient = new ArrayList<>();
    private JPanel panel1;
    private JList userList;
    private JList sysMessageList;
    private JTextField sysMessageFiled;
    private JButton send_Button;
    private DefaultListModel userListModel;
    private DefaultListModel sysMessageListModel;
    private Map<String, List<String>> groups = new HashMap<>();



    public void start() throws Exception {
        JFrame frame = new JFrame("服务器");
        frame.setContentPane(this.panel1);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

//        聊天信息、好友列表绑定模型
        userListModel = new DefaultListModel();
        userList.setModel(userListModel);

        sysMessageListModel = new DefaultListModel();
        sysMessageList.setModel(sysMessageListModel);
        serverSocket = new ServerSocket(port);
        System.out.println("Server started, listening on port " + port);

        while (true) {
            Socket clientSocket = serverSocket.accept();
            new Thread(new ClientHandler(clientSocket)).start();
        }
    }
    class ClientHandler implements Runnable {
        private Socket clientSocket;
        private DataInputStream input;
        private DataOutputStream output;
        private String account;

        ClientHandler(Socket clientSocket) throws Exception {
            this.clientSocket = clientSocket;
            this.input = new DataInputStream(clientSocket.getInputStream());
            this.output = new DataOutputStream(clientSocket.getOutputStream());
        }

        @Override
        public void run() {
            try {
                while (true) {
                    String message = readDecrypt(input);
                    System.out.println("Received: " + message);
                    String[] parts = message.split("&", 4);
                    int code = Integer.parseInt(parts[0]);
                    account = parts[1];

                    List<String> groupMembers = new ArrayList<>(); // 初始化为一个空列表
                    String groupName = parts[1];
                    groupMembers = groups.get(groupName);

                    switch (code) {
                        case 1111:
                            clients.put(account, output);
                            onlineClient.add(account);
                            userListModel.addElement(account);
                            sendOnlineList(account);
                            broadcast("1111&"+account);
                            break;

                        case 2333:
                            broadcast("5555&"+account + ";" + parts[2]);
                            break;

                        case 1333:

                            String recipient = parts[2];
                            String privateMessage = parts[3];
                            sendTo(recipient, account +";"+ privateMessage);
                            break;

                        case 5555: // 创建小组
                            groupName = parts[1];
                            groups.put(groupName, new ArrayList<>());
                            String account = parts[2];
                            groupMembers = groups.get(groupName);
                            groupMembers.add(account);
                            break;

                        case 6666: // 添加成员到小组
                            String newMember = parts[2];
                            if (groupMembers != null) {
                                groupMembers.add(newMember);
                                DataOutputStream output = clients.get(newMember);
                                encryptWrite("6666&"+groupName, output);
                            }
                            break;
                        case 7777: // 从小组中移除成员
                            String memberToRemove = parts[2];
                            if (groupMembers != null) {
                                groupMembers.remove(memberToRemove);
                                DataOutputStream output = clients.get(memberToRemove);
                                encryptWrite("7777&"+groupName, output);
                            }
                            break;
                        case 8888://小组消息
                            groupName = parts[1];
                            groupMembers = groups.get(groupName);
                            if (groupMembers != null) {
                                broadcastToGroup(groupName,parts[2]);
                            }
                            break;

                        default:
                            System.out.println("Unknown message type: " + code);
                            break;
                    }
                }
            } catch (EOFException | SocketException e) {
                System.err.println("Connection was closed by client or network error occurred.");
            } catch (Exception e) {
                e.printStackTrace();

            } finally {
                clients.remove(account);
                onlineClient.remove(account);
                userListModel.removeElement(account);
                System.out.println(account+"下线");
                try {
                    broadcast("4444&"+account);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                try {
                    if (clientSocket != null) {
                        clientSocket.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //广播
        public void broadcast(String message) throws Exception {
            for (DataOutputStream output : clients.values()) {
                encryptWrite(message, output);
            }
        }
        //小组广播
        public void broadcastToGroup(String groupName, String message) throws Exception {
            List<String> groupMembers = groups.get(groupName);
            if (groupMembers != null) {
                for (String member : groupMembers) {
                    DataOutputStream output = clients.get(member);
                    if (output != null) {
                        encryptWrite("8888&"+groupName+"&"+message, output);
                    }
                }
            }
        }

        //私聊
        private void sendTo(String recipient, String message) throws Exception {
            DataOutputStream output = clients.get(recipient);
            if (output != null) {
//                private_encryptWrite(message,output);
                encryptWrite("0000&"+message, output);
            } else {
                System.out.println("Recipient not found: " + recipient);
            }
        }
        //更新用户列表
        private void sendOnlineList(String recipient)throws Exception{
            DataOutputStream output = clients.get(recipient);
            if (output != null) {
                encryptWrite("2222&" + String.join(",", onlineClient), output);
            } else {
                System.out.println("Recipient not found: " + recipient);
            }
        }

    }

    public Server() {
        send_Button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                refresh_message();
            }
        });

        sysMessageFiled.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ENTER)
                    refresh_message();
            }
        });
        userList.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) { // 双击事件
                    String selectedUser = userList.getSelectedValue().toString();
                    int confirm = JOptionPane.showConfirmDialog(null, "是否要强制下线用户:" + selectedUser, "强制下线", JOptionPane.YES_NO_OPTION);
                    if (confirm == JOptionPane.YES_OPTION) {
                        forceDisconnect(selectedUser);
                    }
                }
            }
        });

    }
    输入
    //给所有用户、群聊发送系统消息
    private void refresh_message() {
        String message = sysMessageFiled.getText();
        for (DataOutputStream output : clients.values()) {
            try {
                encryptWrite("0000&系统消息"+";("+nowDate()+"):"+message, output);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
        sysMessageFiled.setText("");

        sysMessageListModel.addElement("系统消息"+"("+nowDate()+"):"+message);
//        自动往下滚
        sysMessageList.ensureIndexIsVisible(sysMessageListModel.size() - 1);
    }

    // 强制下线用户
    private void forceDisconnect(String account) {
        DataOutputStream output = clients.get(account);
        if (output != null) {
            try {
                encryptWrite("3333",output); // 发送下线信号给客户端
                output.close();
                clients.remove(account); // 在服务器端移除该客户端
                broadcast("4444&" + account); // 广播下线信息
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void broadcast(String message) {
        for (DataOutputStream output : clients.values()) {
            try {
                encryptWrite(message, output);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
    }


    public void encryptWrite(String src,DataOutputStream output)throws IOException{
        char[] char_arr = src.toCharArray();
        //加密
        for(int i=0;i<char_arr.length;i++){
            output.writeChar(char_arr[i]+13);
        }
        //结束标识符
        output.writeChar(2333);
        System.out.println(output);
        output.flush();
    }

    public String readDecrypt(DataInputStream input)throws IOException{
        String rtn = "";
        while(true){
            int char_src = input.readChar();
            if(char_src!=2333){
                rtn += (char)(char_src-13);
            }else{
                break;
            }
        }
        return rtn;
    }
    public String nowDate(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formatDateTime = now.format(formatter);
        return formatDateTime;
    }

    public static void main(String[] args) {
        try {
            Server server = new Server(); // 创建Server对象
            server.start(); // 运行服务器
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

 客户端源代码

package Chat;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.net.Socket;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.time.LocalDateTime;
import java.lang.Object;

public class Client {
    private String IP = "127.0.0.1";
    private int port = 5000;
    public Socket socket = null;
    public DataOutputStream output = null;
    public DataInputStream input = null;
    public String send;
    public String account ;
    public String receiver = "聊天大厅";
    private JPanel panel1;
    private JTextField message_Field;
    private JButton send_Button;
    private JList message_List;
    private JList friendList;
    private JLabel ReceiverName;
    private JButton createGroupButton;
    private JButton addMemberButton;
    private JButton removeMemberButton;
    private List<String> onlineUser = new ArrayList<>();
    private DefaultListModel messageListModel;
    private DefaultListModel friendListModel;
    private Map<String,DefaultListModel> chatRecord = new HashMap<>();
    private DefaultListModel chatHallRecord = new DefaultListModel();
    private DefaultListModel systemRecord = new DefaultListModel();
    private Set<String> highlightFriend = new HashSet<>();
//    private Set<String> Group = new HashSet<>();

    private List<String> groups = new ArrayList<String>();


    public static void main(String[] args) throws IOException {
        Client client = new Client("哈哈哈");
        client.run();
    }

    public Client() {
        this.account = "momo";
        init();
    }
    public Client(String account) {
        this.account = account;
        init();
    }

    private void init(){
        chatRecord.put("系统消息",systemRecord);
        chatRecord.put("聊天大厅",chatHallRecord);
        ReceiverName.setText(receiver);
        message_List.setModel(chatHallRecord);
        message_List.ensureIndexIsVisible(chatHallRecord.size() - 1);

        friendList.setCellRenderer(new HighlightedListCellRenderer());

        send_Button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(receiver == "系统消息"){
                    JOptionPane.showMessageDialog(null,"无法向系统发送消息!");
                }else{
                    refresh_message();
                }
            }
        });

        message_Field.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ENTER) {
                    if(receiver == "系统消息"){
                        JOptionPane.showMessageDialog(null,"无法向系统发送消息!");
                    }else{
                        refresh_message();
                    }
                }
            }
        });

        friendList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                String selectFriend = (String) friendList.getSelectedValue();
                if (selectFriend!=receiver){
                    message_Field.setText("");
                    if(selectFriend == null || selectFriend == "聊天大厅"){
                        receiver = "聊天大厅";
                    }else if(chatRecord.containsKey(selectFriend)){
                        receiver = selectFriend;
                    }else{
                        receiver = selectFriend;
                        chatRecord.put(receiver, new DefaultListModel());
                    }
                    ReceiverName.setText(receiver);
                    DefaultListModel receiveChatHistory = chatRecord.get(receiver);
                    message_List.setModel(receiveChatHistory);
                    message_List.ensureIndexIsVisible(receiveChatHistory.size() - 1);

                    if (highlightFriend.contains(receiver)) {
                        highlightFriend.remove(receiver);
                    }
                    friendList.repaint();
                    friendList.revalidate();
                }

                for (Map.Entry<String,DefaultListModel> entry : chatRecord.entrySet()) {
                    String key = entry.getKey();
                    DefaultListModel value = entry.getValue();
                    System.out.println("Key = " + key + ", Value = " + value);
                }
            }
        });

        createGroupButton.addActionListener(e -> {
            String groupName = JOptionPane.showInputDialog("请输入小组名:");
            if (groupName != null && !groupName.isEmpty()) {
                try {
                    encryptWrite("5555&" + groupName+"&"+account, output);
                    friendListModel.addElement(groupName);
                    groups.add(groupName);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });

        addMemberButton.addActionListener(e -> {
            // 创建一个列表模型,并添加所有在线用户
            DefaultListModel<String> listModel = new DefaultListModel<>();
            for (String user : onlineUser) {
                listModel.addElement(user);
            }

            JList<String> list = new JList<>(listModel);
            list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // 允许选择多个用户

            int response = JOptionPane.showConfirmDialog(null, new JScrollPane(list), "请选择要添加的成员", JOptionPane.OK_CANCEL_OPTION);

            if (response == JOptionPane.OK_OPTION) {
                List<String> selectedUsers = list.getSelectedValuesList();
                for (String user : selectedUsers) {
                    try {
                        encryptWrite("6666&" + receiver + "&" + user, output);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });

        removeMemberButton.addActionListener(e -> {
            // 创建一个列表模型,并添加所有在线用户
            DefaultListModel<String> listModel = new DefaultListModel<>();
            for (String user : onlineUser) {
                listModel.addElement(user);
            }

            JList<String> list = new JList<>(listModel);
            list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // 允许选择多个用户

            int response = JOptionPane.showConfirmDialog(null, new JScrollPane(list), "请选择要删除的成员", JOptionPane.OK_CANCEL_OPTION);

            if (response == JOptionPane.OK_OPTION) {
                List<String> selectedUsers = list.getSelectedValuesList();
                for (String user : selectedUsers) {
                    try {
                        encryptWrite("7777&" + receiver + "&" + user, output);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });
    }
    //发送信息
    // 刷新消息列表
    private void refresh_message() {
        String message = message_Field.getText();
        message_Field.setText("");
        String send2 ="";
        //
        if (groups.contains(receiver)) { // 如果接收者是一个小组
            send2 = "8888&" + receiver + "&" + account +"(" + nowDate()+"):"+message; // 使用新的消息类型8888来发送小组消息
        } else if(!receiver.equals("聊天大厅")){//私聊
            send2 = "1333&" + account + "&" + receiver + "&(" + nowDate()+"):"+message;

        }else{//群聊
            send2 = "2333&" + account + "&(" + nowDate()+"):"+message;
        }
        try {
            encryptWrite(send2, output);
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        System.out.println(send2);

        if(chatRecord.containsKey(receiver)){
            DefaultListModel receiveChatHistory = chatRecord.get(receiver);
            message_List.setModel(receiveChatHistory);
            if(!receiver.equals("聊天大厅")&&!groups.contains(receiver))
                receiveChatHistory.addElement(account+"("+nowDate()+"):"+message);
            message_List.ensureIndexIsVisible(receiveChatHistory.size() - 1);
        }else{
            messageListModel = new DefaultListModel();
            chatRecord.put(receiver, messageListModel);
            DefaultListModel receiveChatHistory = chatRecord.get(receiver);
            message_List.setModel(receiveChatHistory);
            receiveChatHistory.addElement(account+"("+nowDate()+"):"+message);
            message_List.ensureIndexIsVisible(receiveChatHistory.size() - 1);
        }
    }
    public void run() throws IOException {
        try {
            JFrame frame = new JFrame(account);
            frame.setContentPane(this.panel1);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
            frame.toFront();
            frame.requestFocus();


            // 线程,每秒更新聊天记录
            new Thread(() -> {
                while (true) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        // 这里添加更新聊天记录或好友列表的代码
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

            Thread.sleep(250);

            new Thread(() -> {
                //        聊天信息、好友列表绑定模型
                messageListModel = new DefaultListModel();
                message_List.setModel(messageListModel);
                message_List.updateUI();
                message_List.ensureIndexIsVisible(messageListModel.size() - 1);

                friendListModel = new DefaultListModel();
                friendList.setModel(friendListModel);
                friendListModel.addElement("系统消息");
                friendListModel.addElement("聊天大厅");
                receiver = "聊天大厅";
                message_List.setModel(chatHallRecord);
                message_List.ensureIndexIsVisible(chatHallRecord.size() - 1);

                try {
                    socket = new Socket(IP, port);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                try {
                    output = new DataOutputStream(socket.getOutputStream());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                try {
                    input = new DataInputStream(socket.getInputStream());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //建立连接,上线
                //把昵称发送给server,以便告知其加入聊天室
                send = "1111&"+account;
                try {
                    encryptWrite(send, output);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //接收消息
                while (true) {
                    System.out.println(input);
                    String receive = null;
                    try {
                        receive = readDecrypt(input);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    //如果收到 3333 则下线
                    if ("3333".equals(receive)) {
                        JOptionPane.showMessageDialog(null,"你已被强制下线!");
                        frame.dispose();
                        try {
                            input.close();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            output.close();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            socket.close();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        System.exit(0);
                    }
                    String []parts = receive.split("&");
                    System.out.println(parts[0]);
                    System.out.println(parts[1]);
                    SwingUtilities.invokeLater(()-> {
                        if (parts[0].equals("1111")) {
                            if (!parts[1].equals(account)) {//添加新进入的客户端
                                friendListModel.addElement(parts[1]);
                                onlineUser.add(parts[1]);

                            }
                        } else if (parts[0].equals("2222")) {//添加之前进入的客户端
                            String[] onlineFriend = parts[1].split(",");
                            for (String friend : onlineFriend) {
                                if(!friend.equals(account)) {
                                    friendListModel.addElement(friend);
                                    onlineUser.add(friend);
                                }
                            }
                        } else if (parts[0].equals("4444")) {//离线
                            friendListModel.removeElement(parts[1]);
                            onlineUser.remove(parts[1]);
                        } else if (parts[0].equals("0000")) {//私聊
                            String sender = parts[1].split(";")[0];
                            System.out.println(sender);
//                    messageListModel.addElement(parts[1]);
                            String message = sender+parts[1].split(";")[1];
                            if (!chatRecord.containsKey(sender)) {
                                chatRecord.put(sender, new DefaultListModel());
                            }
                            DefaultListModel senderChatHistory = chatRecord.get(sender);
                            senderChatHistory.addElement(message);
                            System.out.println("receiver:"+receiver);
                            // 如果这是当前显示的聊天窗口,立即在聊天窗口中显示这条消息
                            if (sender.equals(receiver)) {
                                message_List.setModel(senderChatHistory);
                                message_List.ensureIndexIsVisible(senderChatHistory.size() - 1);
                            }else{
                                highlightFriend.add(sender);
                                friendList.repaint();
                                friendList.revalidate();
                            }
                        }else if (parts[0].equals("8888")) { // 如果是小组消息
                            String groupName = parts[1];
                            String message = parts[2];
                            DefaultListModel groupChatHistory = chatRecord.get(groupName);
                            groupChatHistory.addElement(message);
                            if (groupName.equals(receiver)) { // 如果这是当前显示的小组
                                message_List.setModel(groupChatHistory);
                                message_List.ensureIndexIsVisible(groupChatHistory.size() - 1);
                            } else {
                                highlightFriend.add(groupName);
                                friendList.repaint();
                                friendList.revalidate();
                            }
                        } else if(parts[0].equals("6666")){
                            friendListModel.addElement(parts[1]);
                            groups.add(parts[1]);
                        }else if(parts[0].equals("7777"))
                        {
                            friendListModel.removeElement(parts[1]);
                            groups.remove(parts[1]);
                        }else if(parts[0].equals("5555")){
                            //更新群聊聊天记录
                            String [] part = parts[1].split(";");
                            String message = part[0]+part[1];
                            chatHallRecord.addElement(message);
                            if ("聊天大厅".equals(receiver)) {
                                message_List.setModel(chatHallRecord);
                                message_List.ensureIndexIsVisible(chatHallRecord.size() - 1);
                            }else{
                                highlightFriend.add("聊天大厅");
                                friendList.repaint();
                                friendList.revalidate();

                            }
                        }else{
                            System.out.println("非法字符!");
                        }
                    });
                }
            }).start();

        }catch(Exception e){
            e.printStackTrace();
        } finally{
            try {
                if (socket != null)
                    socket.close();
                input.close();
                output.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public void encryptWrite(String src,DataOutputStream output)throws IOException {
        //将一个字符串转化为字符数组
        char[] char_arr = src.toCharArray();
        //加密操作
        for(int i = 0;i<char_arr.length;i++){
            output.writeChar(char_arr[i]+13);
        }
        //用作结束标志符
        output.writeChar(2333);
        output.flush();
    }
    //读取并解密
    public String readDecrypt(DataInputStream input)throws IOException{
        String rtn="";
        while(true){
            int char_src =input.readChar();
            if(char_src!=2333 && char_src!=1333 && char_src!=1111 &&char_src!=3333  ){
                rtn=rtn+(char)(char_src-13);
            }else{
                break;
            }
        }
        System.out.println(rtn);
        return rtn;
    }
    public String nowDate(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formatDateTime = now.format(formatter);
        return formatDateTime;
    }

    //    点亮用户
    public class HighlightedListCellRenderer extends DefaultListCellRenderer {
        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (highlightFriend.contains(value)) {
                component.setBackground(Color.ORANGE);
            } else {
                component.setBackground(Color.white);
            }
            return component;
        }
    }

}

 登录界面源代码文章来源地址https://www.toymoban.com/news/detail-767047.html

package Chat;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class Login {
    private JPanel panel1;
    private JButton Login_Button;
    private JTextField account_Filed;
    private JTextField password_Filed;
    private JLabel welcome_titile;
    private JFrame frame;
    private static final String ACCOUNT_FILE = "./src/Chat/account.txt";
    private static final Map<String, String> accounts = new HashMap<>();
    private String IP = "127.0.0.1";
    private int port = 5000;



    public Login() {

        loadAccounts();
        setComponents(panel1);
        Login_Button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String account = account_Filed.getText();
                String password = password_Filed.getText();
                //防止未输入,或输入制表符
                if(account == null || account.trim().equals("")){
                    JOptionPane.showMessageDialog(null,"账号不能为空");
                    return;
                }
                if(password == null || password.trim().equals("")){
                    JOptionPane.showMessageDialog(null,"密码不能为空");
                    return;
                }
                if (login(account, password)) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            Client client = new Client(account);
                            try {
                                client.run();
                            } catch (IOException ex) {
                                throw new RuntimeException(ex);
                            }
                        }
                    });
                    frame.dispose();
                } else {
                    JOptionPane.showMessageDialog(null,"账户名或密码错误!");
                }
            }
        });
    }
    private void setComponents(JPanel panel1){

    }

    private static boolean login(String account, String password) {
        if (accounts.containsKey(account)) {
            String storedPassword = accounts.get(account);
            if (storedPassword.equals(password)) {
                return true;
            }
        } else {
            accounts.put(account, password);
            saveAccounts();
            return true;
        }

        return false;
    }

    private static void loadAccounts() {
        try (BufferedReader reader = new BufferedReader(new FileReader(ACCOUNT_FILE))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split(":");
                if (parts.length == 2) {
                    String username = parts[0];
                    String password = parts[1];
                    accounts.put(username, password);
                }
            }
        } catch (IOException e) {
            // 处理文件读取异常
            e.printStackTrace();
        }
    }

    private static void saveAccounts() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(ACCOUNT_FILE))) {
            for (Map.Entry<String, String> entry : accounts.entrySet()) {
                String username = entry.getKey();
                String password = entry.getValue();
                String line = username + ":" + password;
                writer.write(line);
                writer.newLine();
            }
        } catch (IOException e) {
            // 处理文件写入异常
            e.printStackTrace();
        }
    }

    public void run(){
        frame = new JFrame("Login");
        frame.setContentPane(this.panel1);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Login().run();
    }

}

到了这里,关于【Java socket编程】多人聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Java Socket写一个多线程的聊天室(附源码)

    Socket编程是在TCP/IP上的网络编程,但是Socket在上述模型的什么位置呢。这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来 ​ 我们可以发现Socket就在应用程序的传输层和应用层之间,设计了一个Socket抽象层,传输层的底一层的服务提供给Socket抽象层,S

    2024年02月10日
    浏览(54)
  • 【Linux网络编程】基于UDP实现多人聊天室

    UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。 数据报格式套接字 SOCK_DGRAM 采用UDP只管发送数据而不去验证发送数据的正确性,不论传输是否被接收,数据流是否有丢失,都不再重新发

    2024年02月08日
    浏览(56)
  • 多人聊天室(带私聊功能)Linux网络编程基础

    在和同学一起努力下终于完成了期末作业哈哈哈哈 文章目录 目录 前言 一、需求分析 二、功能设计 1.服务器端: 2.客户端: 三、流程图: 编程流程图: 服务器流程图: 客户端流程图: 四、运行效果: 项目源码: 服务器源码 客户端源码: 总结: Linux网络编程是我们这学

    2024年02月09日
    浏览(59)
  • 【一】【socket聊天室】-多线程,socket编程

    本文主要实现基于socket编程的聊天室,主要分为下面三个步骤: (1)多用户聊天:一个服务器多个客户端,客户端信息显示在公共的服务端窗口,利用 多线程 实现;          ——客户端双线程:一个接受线程一个发送线程(主线程);          ——服务器单线程:接收

    2024年02月08日
    浏览(45)
  • C语言Socket编程TCP简单聊天室

    这是一个使用C语言进行套接字编程实现的简单聊天室, 使用Pthread库进行多线程执行 服务端: svr.c 客户端: cli.c Makefile: Makefile 执行编译 启动服务器 启动客户端 聊天 退出

    2024年02月03日
    浏览(54)
  • .NET编程——利用C#实现基于Socket类的聊天室(WinForm)

    在学习C#和MySQL实现注册登录和TCP协议的Socket通信后,本文将介绍如何利用Socket类中的异步通信函数来实现本地聊天室功能, Socket通信限制了客户端与客户端之间的通信,客户端只能接收来自服务器的消息而不能接收到客户端发送的消息,因此服务器最佳的选择是起到一个中

    2023年04月21日
    浏览(90)
  • Python多人聊天室

    链接:https://pan.baidu.com/s/1kzxiLTkvdxGAMgF3SQzcaw?pwd=vb9h 提取码:vb9h 利用socket方式编写一个多人聊天室程序,可以实现多个用户之间的群聊功能,私聊功能,显示当前用户功能 在聊天室程序中增加利用ftp实现文件的上传,下载,删除,查看当前文件功能 在聊天室程序中增加利用

    2024年02月03日
    浏览(59)
  • 基于Python web的多人聊天室

              本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现。这个系统利用了多种先进的技术,如Django、Channels、WebSocket,来实现即时通信,并利用MySQL和Redis作为数据库,同时还采用了多种前端技术,如bootstrap、CSS、html和js,来提供出色的用户体验。该系

    2024年02月16日
    浏览(40)
  • vue3-多人聊天室角色识别(全栈)

    主要技术栈是vue3,springboot,websocket,element-plus 主要目的是复习和梳理 发送信息,包装信息,转json,用socket发送到后端,使输入栏清空 后端解析json,因为是socket接口,所以不能用@requestbody解析json,用以下方式解析json 设置发送时间为当前时间,然后执行mapper数据库插入 广

    2024年02月11日
    浏览(39)
  • C语言实现--基于UDP的多人在线聊天室

    目录 实现功能 实现思想 实现代码(部分及详解) 服务端部分代码 客户端部分代码 实现效果 项目中出现的问题和解决方法 项目整体代码展示 代码优化思路 服务端代码 客户端代码 服务端可以同时连接多个客户端; 新的客户端连接服务端时,可以在服务端显示自己的名字并

    2024年02月04日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包