Java多人聊天室具体实现类代码

客户端

Client

package Client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Java聊天室客户端
 *
 * @author 郑黑脸
 * @version 1.0
 */

//继承Thread类,使用多线程
public class Client extends Thread {
    //创建客户端Socket对象
    public Socket c_socket;
    private Client_chatFrame c_chatFrame;
    private Client_enterFrame c_enterFrame;
    private Client_singleFrame c_singleFrame;
    //创建数据输入流对象
    public DataInputStream dis = null;
    //创建数据输出流对象
    public DataOutputStream dos = null;
    //退出标记
    private boolean flag_exit = false;
    //定义线程id
    private int threadID;

    //Map集合存储单人聊天界面
    public Map<String, Client_singleFrame> c_singleFrames;
    //List集合存储即时在线用户信息
    public List<String> username_online;
    //List集合存储用户id
    public List<Integer> clientuserid;
    //初始化用户名
    public String username = null;
    //读到的信息
    public String chat_re;

    //getter, setter方法
    public Client_chatFrame getC_chatFrame() {
        return c_chatFrame;
    }

    public Client_singleFrame getC_singlFrame() {
        return c_singleFrame;
    }

    public void setC_singlFrame(Client_singleFrame c_singlFrame) {
        this.c_singleFrame = c_singlFrame;
    }

    public void setC_chatFrame(Client_chatFrame c_chatFrame) {
        this.c_chatFrame = c_chatFrame;
    }

    public Client_enterFrame getC_enterFrame() {
        return c_enterFrame;
    }

    public void setC_enterFrame(Client_enterFrame c_enterFrame) {
        this.c_enterFrame = c_enterFrame;
    }

    public int getThreadID() {
        return threadID;
    }

    public void setThreadID(int threadID) {
        this.threadID = threadID;
    }

    public Client() {
        //创建集合对象
        c_singleFrames = new HashMap<String, Client_singleFrame>();
        username_online = new ArrayList<String>();
        clientuserid = new ArrayList<Integer>();
//		signlechatuse = new ArrayList<String>();
    }

    public static void main(String[] args) {
        Client client = new Client();
        Client_enterFrame c_enterFrame = new Client_enterFrame(client);
        client.setC_enterFrame(c_enterFrame);
        //显示窗体
        c_enterFrame.setVisible(true);
    }

    /**登录
     *
     * @param username  用户名
     * @param hostIp    主机IP
     * @param hostPort  主机端口
     * @return
     *
     * 登录模块
     * 加入登录错误提示功能
     * 可提示的内容有:端口号错误,主机地址错误,连接服务异常
     * 如果三项都输入正确,则返回true
     *
     */
    public String login(String username, String hostIp, String hostPort) {
        this.username = username;
        String login_mess = null;
        try {
            c_socket = new Socket(hostIp, Integer.parseInt(hostPort));
        } catch (NumberFormatException e) {
            login_mess = "连接的服务器端口号port为整数,取值范围为:1024<port<65535";
            return login_mess;
        } catch (UnknownHostException e) {
            login_mess = "主机地址错误";
            return login_mess;
        } catch (IOException e) {
            login_mess = "连接服务其失败,请稍后再试";
            return login_mess;
        }
        return "true";
    }

    //显示聊天窗体
    public void showChatFrame(String username) {
        getDataInit();
        c_chatFrame = new Client_chatFrame(this, username);
        c_chatFrame.setVisible(true);
        //将退出标记置为true
        flag_exit = true;
        //启动该聊天的线程
        this.start();

    }

    //获取数据单元模块
    //从输入流中获取数据,封装到通道
    private void getDataInit() {
        try {
            dis = new DataInputStream(c_socket.getInputStream());
            dos = new DataOutputStream(c_socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * 重写run方法
     * 加入判断功能
     */
    public void run() {
        while (flag_exit) {
            try {
                //从所包含的输入流中读取此操作的字节数
                chat_re = dis.readUTF();
            } catch (IOException e) {
                flag_exit = false;
                if (!chat_re.contains("@serverexit")) {
                    chat_re = null;
                }
            }
            if (chat_re != null) {
                if (chat_re.contains("@clientThread")) {
                    int local = chat_re.indexOf("@clientThread");
                    setThreadID(Integer.parseInt(chat_re.substring(0, local)));
                    try {
                        dos.writeUTF(username + "@login" + getThreadID() + "@login");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    if (chat_re.contains("@userlist")) {
                        c_chatFrame.setDisUsers(chat_re);
                    } else {
                        if (chat_re.contains("@chat")) {
                            c_chatFrame.setDisMess(chat_re);
                        } else {
                            if (chat_re.contains("@serverexit")) {
                                c_chatFrame.closeClient();
                            } else {
                                if (chat_re.contains("@single")) {
                                    c_chatFrame.setSingleFrame(chat_re);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    //传输错误
    public void transMess(String mess) {
        try {
            dos.writeUTF(username + "@chat" + getThreadID() + "@chat" + mess + "@chat");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //退出聊天
    public void exitChat() {
        try {
            dos.writeUTF(username + "@exit" + getThreadID() + "@exit");
            flag_exit = false;
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //退出登录
    public void exitLogin() {
        System.exit(0);
    }

    //退出客户端
    public void exitClient() {
        flag_exit = false;
        System.exit(0);
    }
}

服务器端

Server

package Server;


public class Server {

    private ServerFrame serverFrame;
    private ServerThread serverThread;

    public ServerFrame getServerFrame() {
        return serverFrame;
    }

    public void setServerFrame(ServerFrame serverFrame) {
        this.serverFrame = serverFrame;
    }

    public Server() {
    }

    //启动服务器
    public void startServer() {
        try {
            serverThread = new ServerThread(serverFrame);
        } catch (Exception e) {
            System.exit(0);
        }
        serverThread.setFlag_exit(true);
        serverThread.start();
    }

    //停止服务器
    public void stopServer() {
        synchronized (serverThread.messages) {
            String str = "@serverexit";
            serverThread.messages.add(str);
        }
        serverThread.serverFrame.setDisMess("@exit");
        serverThread.serverFrame.setDisUsers("@exit");
        serverThread.stopServer();
    }

    
    public static void main(String[] args) {
        Server server = new Server();
        ServerFrame serverFrame = new ServerFrame(server);
        server.setServerFrame(serverFrame);
        serverFrame.setVisible(true);
    }

    //关闭服务器
    public void close() {
        if (serverThread != null) {
            if (serverThread.isAlive()) {
                serverThread.stopServer();
            }
        }
        System.exit(0);
    }

}
ServerThread

package Server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

public class ServerThread extends Thread {

    //服务端Socket对象
    public ServerSocket serverSocket;
    //信息 用Vector集合存储
    public Vector<String> messages;
    //用户线程 用Vector集合存储
    public Vector<ClientThread> clients;
    //Map集合存储用户信息
    public Map<Integer, String> users;
    //广播对象
    public BroadCast broadcast;
    //定义服务器端端口号
    public int Port = 5000;
    public boolean login = true;
    public ServerFrame serverFrame;
    private boolean flag_exit = false;


    //服务器线程
    public ServerThread(ServerFrame serverFrame) {
        this.serverFrame = serverFrame;
        //创建集合存储信息
        messages = new Vector<String>();
        clients = new Vector<ClientThread>();
        users = new HashMap<Integer, String>();
        try {
            serverSocket = new ServerSocket(Port);
        } catch (IOException e) {
            this.serverFrame.setStartAndStopUnable();
            System.exit(0);
        }
        //广播线程
        broadcast = new BroadCast(this);
        broadcast.setFlag_exit(true);
        broadcast.start();
    }

    @Override
    public void run() {
        Socket socket;
        //当标记为ture的时候检查服务器端Socket是否在开启状态,如果关闭,将标记置为false
        while (flag_exit) {
            try {
                if (serverSocket.isClosed()) {
                    flag_exit = false;
                } else {
                    try {
                        //监听客户端socket
                        socket = serverSocket.accept();
                    } catch (SocketException e) {
                        socket = null;
                        flag_exit = false;
                    }

                    //当客户端socket不为null时,启动客户端线程
                    if (socket != null) {
                        ClientThread clientThread = new ClientThread(socket, this);
                        clientThread.setFlag_exit(true);
                        clientThread.start();
                        synchronized (clients) {
                            clients.addElement(clientThread);
                        }
                        synchronized (messages) {
                            users.put((int) clientThread.getId(), "@login@");
                            messages.add(clientThread.getId() + "@clientThread");
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //停止服务器
    public void stopServer() {
        try {
            if (this.isAlive()) {
                serverSocket.close();
                setFlag_exit(false);
            }
        } catch (Throwable e) {
        }
    }

    //设置标记退出
    public void setFlag_exit(boolean b) {
        flag_exit = b;
    }
}
ClientThread


package Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 客户端线程
 *
 * @author 郑黑脸
 * @version 1.0
 *
 * 用户端线程的实现类
 */

public class ClientThread extends Thread {

    //服务器客户端Socket对象
    public Socket clientSocket;
    //服务端线程对象
    public ServerThread serverThread;
    //数据输入流对象
    public DataInputStream dis;
    //数据输出流对象
    public DataOutputStream dos;
    //客户端用户ID
    public String client_userID;
    //标记
    private boolean flag_exit = false;

    //客户端Socket
    public ClientThread(Socket socket, ServerThread serverThread) {
        clientSocket = socket;
        this.serverThread = serverThread;
        try {
            //封装数据输入输出流
            dis = new DataInputStream(clientSocket.getInputStream());
            dos = new DataOutputStream(clientSocket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //重写run方法
    @Override
    public void run() {
        while (flag_exit) {
            try {
                String Message = dis.readUTF();
                if (Message.contains("@login")) {
                    //以@login分割userInfo字符串,得到Info
                    String[] userInfo = Message.split("@login");
                    int userID = Integer.parseInt(userInfo[1]);
                    serverThread.users.remove(userID);
                    if (serverThread.users.containsValue(userInfo[0])) {
                        for (int i = 0; i < serverThread.clients.size(); i++) {
                            int id = (int) serverThread.clients.get(i).getId();
                            if (serverThread.users.get(id).equals(userInfo[0])) {
                                serverThread.users.remove(id);
                                serverThread.users.put(id, userInfo[0] + "_" + id);
                                break;
                            }
                        }
                        serverThread.users.put(Integer.parseInt(userInfo[1]), userInfo[0] + "_" + userInfo[1]);
                    } else {
                        serverThread.users.put(userID, userInfo[0]);
                    }

                    Message = null;
                    //创建容器 存储线程id和userlist
                    StringBuffer sb = new StringBuffer();
                    synchronized (serverThread.clients) {
                        for (int i = 0; i < serverThread.clients.size(); i++) {
                            int threadID = (int) serverThread.clients.elementAt(i).getId();
                            sb.append((String) serverThread.users.get(new Integer(threadID)) + "@userlist");
                            sb.append(threadID + "@userlist");
                        }
                    }
                    String userNames = new String(sb);
                    serverThread.serverFrame.setDisUsers(userNames);
                    Message = userNames;
                } else {
                    if (Message.contains("@exit")) {
                        String[] userInfo = Message.split("@exit");
                        int userID = Integer.parseInt(userInfo[1]);
                        serverThread.users.remove(userID);
                        Message = null;
                        StringBuffer sb = new StringBuffer();
                        synchronized (serverThread.clients) {
                            for (int i = 0; i < serverThread.clients.size(); i++) {
                                int threadID = (int) serverThread.clients.elementAt(i).getId();
                                if (userID == threadID) {
                                    serverThread.clients.removeElementAt(i);
                                    i--;
                                } else {
                                    sb.append((String) serverThread.users.get(new Integer(threadID)) + "@userlist");
                                    sb.append(threadID + "@userlist");
                                }
                            }
                        }
                        String userNames = new String(sb);
                        if (userNames.equals("")) {
                            serverThread.serverFrame.setDisUsers("@userlist");
                        } else {
                            serverThread.serverFrame.setDisUsers(userNames);
                        }
                        Message = userNames;
                    } else {
                        //聊天显示姓名和发送时间的实现
                        if (Message.contains("@chat")) {
                            String[] chat = Message.split("@chat");
                            StringBuffer sb = new StringBuffer();
                            SimpleDateFormat form = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
                            String date = form.format(new Date());
                            sb.append(chat[0] + "  " + date + "\n");
                            sb.append(chat[2] + "@chat");
                            String str = new String(sb);
                            Message = str;
                            serverThread.serverFrame.setDisMess(Message);
                        } else {
                            if (Message.contains("@single")) {

                            }
                        }
                    }
                }
                synchronized (serverThread.messages) {
                    if (Message != null) {
                        serverThread.messages.addElement(Message);
                    }
                }
                if (Message.contains("@exit")) {
                    this.clientSocket.close();
                    flag_exit = false;
                }
            } catch (IOException e) {
            }
        }
    }

    //关闭客户端线程,并提示服务器的客户端Socket为空
    public void closeClienthread(ClientThread clientThread) {
        if (clientThread.clientSocket != null) {
            try {
                clientThread.clientSocket.close();
            } catch (IOException e) {
                System.out.println("server's clientSocket is null");
            }
        }

        try {
            setFlag_exit(false);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public void setFlag_exit(boolean b) {
        flag_exit = b;
    }
}
BroadCast
package Server;

import java.io.IOException;

/**
 * 广播线程的实现类
 * 
 * @author 郑黑脸
 * 
 * @version 1.0
 */

public class BroadCast extends Thread {
    //客户端线程
    ClientThread clientThread;
    //服务器端线程
    ServerThread serverThread;
    String str;
    private boolean flag_exit = false;

    public BroadCast(ServerThread serverThread) {
        this.serverThread = serverThread;
    }

    @Override
    public void run() {
        boolean flag = true;
        while (flag_exit) {
            synchronized (serverThread.messages) {
                if (serverThread.messages.isEmpty()) {
                    continue;
                } else {
                    str = (String) serverThread.messages.firstElement();
                    serverThread.messages.removeElement(str);
                    if (str.contains("@clientThread")) {
                        flag = false;
                    }
                }
            }
            synchronized (serverThread.clients) {
                for (int i = 0; i < serverThread.clients.size(); i++) {
                    clientThread = serverThread.clients.elementAt(i);
                    if (flag) {
                        try {
                            //向记录的每一个客户端发送数据信息
                            if (str.contains("@exit")) {
                                serverThread.clients.remove(i);
                                clientThread.closeClienthread(clientThread);
                                clientThread.dos.writeUTF(str);
                            }
                            if (str.contains("@chat") || str.contains("@userlist") || str.contains("@serverexit")) {
                                clientThread.dos.writeUTF(str);
                            }
                            if (str.contains("@single")) {
                                String[] info = str.split("@single");
                                int id_thread = Integer.parseInt(info[2]);
                                for (int j = 0; j < serverThread.clients.size(); j++) {
                                    if (id_thread == serverThread.clients.get(j).getId()) {
                                        serverThread.clients.get(j).dos.writeUTF(str);
                                        i = serverThread.clients.size();
                                        break;
                                    }
                                }
                            }
                        } catch (IOException E) {
                        }
                    } else {
                        String value = serverThread.users.get((int) clientThread.getId());
                        if (value.equals("@login@")) {
                            flag = true;
                            try {
                                //向记录的每一个客户端发送数据信息
                                clientThread.dos.writeUTF(str);
                                if (str.contains("@exit")) {
                                    serverThread.clients.remove(i);
                                    clientThread.closeClienthread(clientThread);
                                }
                            } catch (IOException E) {
                            }
                            break;
                        }
                    }
                }
            }
            if (str.contains("@serverexit")) {
                serverThread.users.clear();
                flag_exit = false;
            }
        }
    }

    public void setFlag_exit(boolean b) {
        flag_exit = b;
    }

    
    public void stopBroadCase() {
        flag_exit = false;
    }
}
发布了120 篇原创文章 · 获赞 37 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Zhengxinyu666/article/details/99694909