局域网聊天系统-Java

这个局域网聊天系统,是为了能够在一个没有连接到intent的局域网中,进行聊天的一个程序。本程序包括服务器和客户机两部分,可以实现多人聊天和两个人私聊的一个工具。
开发语言:Java,开发工具:eclipse。
客户机代码如下:
Client.java

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

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.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

	public class Client{//客户端
	
	   JFrame frame;
	   JList<String> userList;//列表组件
	   JTextArea textArea;//文本域
	   JTextField textField;
	   JTextField txt_port,txt_Ip,txt_name;
	   
	   JButton button_start,button_stop,button_send;//连接按钮,断开按钮,发送按钮
	   
	   JPanel north,south;//上、下面板
	   JScrollPane rightScroll,leftScroll;//左右滚动面板
	   JSplitPane centerSplit;//分割面板
	   DefaultListModel<String> listModel;//点击事件
	    
	   private boolean crossFire = false;    
	
	   Socket socket;//套接字
	   PrintWriter writer;
	   BufferedReader reader;
	   MessageThread messageThread;// 负责接收消息的线程
	   private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在线用户集合
	    
	   public void send() {//发送方法
	        if (!crossFire) {
	            JOptionPane.showMessageDialog(frame, "Warning!无法连接服务器", "错误",JOptionPane.ERROR_MESSAGE);
	            return;
	        }
	        String message = textField.getText().trim();
	        if (message == null || message.equals("")) {
	            JOptionPane.showMessageDialog(frame, "Warning! 消息不能为空!", "错误",JOptionPane.ERROR_MESSAGE);
	            return;
	        }
	        sendMessage(frame.getTitle() + "@" + "ALL" + "@" + message);
	        textField.setText(null);
	   }
	
	   public Client() {//创建构造方法
	        textArea = new JTextArea();
	        textArea.setEditable(false);//设置文本域不可读
	        textArea.setForeground(Color.RED);//设置背景颜色位红色
	        
	        textField = new JTextField();
	        txt_port = new JTextField();//端口号
	        txt_Ip = new JTextField();//服务器IP
	        txt_name = new JTextField();//用户名
	        
	        button_start = new JButton("连接");
	        button_stop = new JButton("断开");
	        button_send = new JButton("发送");
	        
	        listModel = new DefaultListModel<String>();
	        userList = new JList<String>(listModel);
	
	        north = new JPanel();
	        north.setLayout(new GridLayout(1, 4));//设置布局方式
	        north.add(new JLabel("端口"));
	        north.add(txt_port);//在JPanel组件中添加端口组件
	        north.add(new JLabel("服务器IP:"));
	        north.add(txt_Ip);//在JPanel组件中添加IP组件 
	        north.add(new JLabel("姓名:"));
	        north.add(txt_name);//添加文本域组件
	        north.add(button_start);//添加按钮组件
	        north.add(button_stop);//添加按钮组件
	        north.setBorder(new TitledBorder("连接信息"));
	
	        rightScroll = new JScrollPane(textArea);
	        rightScroll.setBorder(new TitledBorder("聊天记录区"));
	        
	        leftScroll = new JScrollPane(userList);
	        leftScroll.setBorder(new TitledBorder("在线用户明细"));//设置组件的边框
	        
	        south = new JPanel(new BorderLayout());
	        south.add(textField, "Center");
	        south.add(button_send, "East");
	        south.setBorder(new TitledBorder("写消息"));
	
	        centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll,rightScroll);
	        centerSplit.setDividerLocation(100);//设置分隔条的相对位置
	
	        frame = new JFrame("客户端");
	        frame.add(north, "North");
	        frame.add(centerSplit, "Center");
	        frame.add(south, "South");
	        frame.setSize(750, 350);
	        
	        int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;//获取屏幕的宽度
	        int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;//获取屏幕的高度
	        frame.setLocation((screen_width - frame.getWidth()) / 2,(screen_height - frame.getHeight()) / 2);//设置窗口的相对位置
	        frame.setVisible(true);//设置组件可见
	        
	        // 写消息的文本框中按回车键时事件
	        textField.addActionListener(new ActionListener() {//添加监听,监听文本域消息
	            public void actionPerformed(ActionEvent arg0) {
	                send();
	            }
	        });
	
	        // 单击发送按钮时事件
	        button_send.addActionListener(new ActionListener() {//添加监听,监听发送按钮消息
	            public void actionPerformed(ActionEvent e) {
	                send();
	            }
	        });
	
	        // 单击连接按钮时事件
	        button_start.addActionListener(new ActionListener() {//添加监听,监听连接按钮消息
	            public void actionPerformed(ActionEvent e) {
	                int port;
	                if (crossFire) {
	                    JOptionPane.showMessageDialog(frame, "WARNING!  重复链接","错误", JOptionPane.ERROR_MESSAGE);
	                    return;
	                }
	                try {
	                    try {
	                        port = Integer.parseInt(txt_port.getText().trim());
	                    } catch (NumberFormatException e2) {
	                        throw new Exception("端口号错误!   端口应为整数!");
	                    }
	                    String hostIp = txt_Ip.getText().trim();
	                    String name = txt_name.getText().trim();
	                    if (name.equals("")) {
	                        throw new Exception("姓名不能为空!");
	                    }
	                    
	                    if(hostIp.equals(""))
	                    	throw new Exception("服务器IP不能为空!");
	                    
	                    boolean flag = connectServer(port, hostIp, name);
	                    
	                    if (flag == false) {
	                        throw new Exception("无连接,或连接失败!");
	                    }
	                    
	                    frame.setTitle(name);
	                    JOptionPane.showMessageDialog(frame, "成功连接!");
	                } catch (Exception exc) {
	                    JOptionPane.showMessageDialog(frame, exc.getMessage(),"错误", JOptionPane.ERROR_MESSAGE);
	                }
	            }
	        });
	
	        // 单击断开按钮时事件
	        button_stop.addActionListener(new ActionListener() {//添加监听,监听断开按钮消息
	            public void actionPerformed(ActionEvent e) {
	                if (!crossFire) {
	                    JOptionPane.showMessageDialog(frame, "Warning!重复连接","错误", JOptionPane.ERROR_MESSAGE);
	                    return;
	                }
	                try {
	                    boolean flag = closeConnection();// 断开连接
	                    if (flag == false) {
	                        throw new Exception("断开连接发生异常!");
	                    }
	                    JOptionPane.showMessageDialog(frame, "已断开!");
	                } catch (Exception exc) {
	                    JOptionPane.showMessageDialog(frame, exc.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
	                }
	            }
	        });
	
	        // 关闭窗口时事件
	        frame.addWindowListener(new WindowAdapter() {//添加窗口监听
	            public void windowClosing(WindowEvent e) {
	                if (crossFire) {
	                    closeConnection();//关闭连接
	                }
	                System.exit(0);//退出程序
	            }
	        });
	    }
	   
	    public boolean connectServer(int port, String hostIp, String name) {//连接服务器
	        try {
	            socket = new Socket(hostIp, port);// 根据端口号和服务器Ip建立连接
	            writer = new PrintWriter(socket.getOutputStream());
	            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
	            
	            sendMessage(name + "@" + socket.getLocalAddress().toString()); //发送客户端用户基本信息(用户名和ip地址)
	            
	            messageThread = new MessageThread(reader, textArea);//开启接收消息的线程
	            messageThread.start();
	            crossFire = true;//已经连接上了
	            return true;
	        } catch (Exception e) {
	            textArea.append("与端口号为:" + port + "    IP地址为:" + hostIp+ "   的服务器连接失败!" + "\r\n");
	            crossFire = false;//未连接上
	            return false;
	        }
	    }

	    public void sendMessage(String message) {
	        writer.println(message);
	        writer.flush();
	    }

	    @SuppressWarnings("deprecation")
		public synchronized boolean closeConnection() {//同步方法
	        try {
	            sendMessage("CLOSE");//发送断开连接命令给服务器
	            messageThread.stop();//停止接受消息线程
	            reader.close();//释放资源
	            writer.close();
	            socket.close();
	            crossFire=false;
	            return true;
	        } catch (IOException e1) {
	            e1.printStackTrace();
	            crossFire = true;
	            return false;
	        }
	    }

	    class MessageThread extends Thread {//接收消息线程
	        private BufferedReader reader;
	        private JTextArea textArea;
	        
	        public MessageThread(BufferedReader reader, JTextArea textArea) {//创建线程的构造方法
	            this.reader = reader;
	            this.textArea = textArea;
	        }
	
	        public synchronized void closeCon() throws Exception {//同步方法
	            listModel.removeAllElements();// 清空用户列表
	            reader.close();//关闭连接释放资源
	            writer.close();     
	            socket.close();
	            crossFire = false;//修改状态为断开
	        }
	
	        @SuppressWarnings("unlikely-arg-type")
			public void run() {
	            String message = "";
	            while (true) {
	                try {
	                    message = reader.readLine();
	                    StringTokenizer stringTokenizer = new StringTokenizer(message, "/@");//分解字符串
	                    String command = stringTokenizer.nextToken();//返回下一个
	                    if (command.equals("CLOSE")){// 服务器已关闭命令
	                        textArea.append("服务器已关闭!\r\n");
	                        closeCon();//关闭连接
	                        return;//结束线程
	                    } else if (command.equals("ADD")) {//有用户上线更新在线列表
	                        String username;
	                        String userIp;
	                        if ((username = stringTokenizer.nextToken()) != null&& (userIp = stringTokenizer.nextToken()) != null) {
	                            User user = new User(username, userIp);
	                            onLineUsers.put(username, user);
	                            listModel.addElement(username);
	                        }
	                    } else if (command.equals("DELETE")) {//有用户下线更新在线列表
	                        String username = stringTokenizer.nextToken();
	                        User user = (User) onLineUsers.get(username);
	                        onLineUsers.remove(user);//删除下线用户名及ip
	                        listModel.removeElement(username);//删除在线列表中用户名
	                    } else if (command.equals("USERLIST")) {// 加载在线用户列表
	                        int size = Integer.parseInt(stringTokenizer.nextToken());//使用下一个参数指定的基数,将字符串参数解析为有符号的整数
	                        String username = null;
	                        String userIp = null;
	                        for (int i = 0; i < size; i++) {
	                            username = stringTokenizer.nextToken();
	                            userIp = stringTokenizer.nextToken();
	                            User user = new User(username, userIp);
	                            onLineUsers.put(username, user);//更新在线用户
	                            listModel.addElement(username);//添加用户名
	                        }
	                    } else if (command.equals("MAX")) {//人数达到上限
	                        textArea.append(stringTokenizer.nextToken()+ stringTokenizer.nextToken() + "\r\n");//将用户名及用户IP添加到文本域,提示用户达到上限
	                        closeCon();//关闭连接
	                        JOptionPane.showMessageDialog(frame, "服务器缓冲区已满!", "错误",JOptionPane.ERROR_MESSAGE);//消息对话框
	                        return;// 结束线程
	                    } else {//消息
	                        textArea.append(message + "\r\n");
	                    }
	                } catch (IOException e) {
	                    e.printStackTrace();
	                } catch (Exception e) {
	                    e.printStackTrace();
	                }
	            }
	        }
	    }
	    public static void main(String[] args) {
	        new Client();
	    }
	}

服务器代码如下:
Sever.java

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.StringTokenizer;

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.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

public class Sever  {

    JFrame frame;
    JTextArea contentArea;  //文本域
    JTextField txt_message,txt_max,txt_port;  //用于显示文本信息,设置最大连接人数,设置端口号
    JButton button_start,button_stop ,button_send;//启动按钮,停止按钮,发送按钮
    
    JPanel north,south;        //上面面板,下面面板
    JScrollPane right,left; //左边滚动面板,右边滚动面板
    JSplitPane centerSplit; //分割面板
    JList<String> userList;         //列表组件
    DefaultListModel<String> listModel;//点击事件

    ServerSocket serverSocket;//创建套接字                                        
    ServerThread serverThread;//创建线程
    
    private ArrayList<ClientThread> clients;//创建客户端的集合

    private boolean Fire = false;//创建一个布尔值

    public void send() {//创建一个发送消息的方法send
        if (!Fire) {//判断是是否启动服务器
            JOptionPane.showMessageDialog(frame, "服务器还未启动,不能发送消息!", "错误",JOptionPane.ERROR_MESSAGE);//类提示框
            return;
        }
        if (clients.size() == 0) {
            JOptionPane.showMessageDialog(frame, "没有用户在线,不能发送消息!", "错误",JOptionPane.ERROR_MESSAGE);//判断是否有用户在线
            return;
        }
        String message = txt_message.getText().trim();//文本框内容获取
        if (message == null || message.equals("")) {JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误",JOptionPane.ERROR_MESSAGE);//判断消息框是否有文字
            return;
        }
        sendServerMessage(message);// 群发服务器消息(调用sendServerMessage方法)
        contentArea.append("服务器:" + txt_message.getText() + "\r\n");//在文本域添加服务器发送的新内容
        txt_message.setText(null);
    }
    public Sever() {//创建构造函数
        frame = new JFrame("服务器");//实例化一个服务器窗体对象
        
        contentArea = new JTextArea();//实例化文本域
        contentArea.setEditable(false);//设置文本为不可读状态
        contentArea.setForeground(Color.red);//设置背景颜色为红色
        
        txt_message = new JTextField();//消息编辑
        txt_max = new JTextField();//设置允许连接的最多人数
        txt_port = new JTextField();//设置端口号
        
        button_start = new JButton("启动");//创建启动按钮
        button_stop = new JButton("停止");//创建停止按钮
        button_send = new JButton("发送");//创建发送按钮
        
        button_stop.setEnabled(false);//设置按钮不可用
        listModel = new DefaultListModel<String>();//实例化鼠标点击
        userList = new JList<String>(listModel);//实例化列表框对象

        south = new JPanel(new BorderLayout());//实例化下面面板
        south.setBorder(new TitledBorder("写消息"));//文本按钮
        south.add(txt_message, "Center");//添加文本
        south.add(button_send, "East");//发送文本
        
        left = new JScrollPane(userList);//实例化左边滚动条,传入用户的名字
        left.setBorder(new TitledBorder("在线用户明细"));

        right = new JScrollPane(contentArea);//实例化右边滚动条,传入文本域
        right.setBorder(new TitledBorder("聊天记录区"));//添加滚动面板内容

        centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left,right);//实例化分割线 将面板分割成左右两部分
        centerSplit.setDividerLocation(100);//设置centerSplit的分隔线的相对位置
        
        north = new JPanel();//实例化上面面板
        north.setLayout(new GridLayout(1, 4));//窗口布局
        north.add(new JLabel("人数上限"));//JButton实例添加到JPanel中
        north.add(txt_max);//JButton实例添加到JPanel中
        north.add(new JLabel("端口"));//JButton实例添加到JPanel中
        north.add(txt_port);//JButton实例添加到JPanel中
        north.add(button_start);//JButton实例添加到JPanel中
        north.add(button_stop);//JButton实例添加到JPanel中
        north.setBorder(new TitledBorder("配置信息"));
        
        frame.setLayout(new BorderLayout());//容器使用绝对布局
        frame.add(north, "North");//添加上面板组件
        frame.add(centerSplit, "Center");//添加分割线组件
        frame.add(south, "South");//条件下面板组件
        frame.setSize(750, 350);//设置组件的宽和高
        
        int s_width=Toolkit.getDefaultToolkit().getScreenSize().width;//获取电脑屏幕的宽
        int s_height=Toolkit.getDefaultToolkit().getScreenSize().height;//获取电脑屏幕的高
        frame.setLocation((s_width - frame.getWidth()) / 2,(s_height - frame.getHeight()) / 2);//设置组件左上角的坐标,将其放在屏幕中间
        frame.setVisible(true);//设置窗体可见

        frame.addWindowListener(new WindowAdapter() {//添加窗体监听事件
            public void windowClosing(WindowEvent e) {// 窗口关闭时触发
                if (Fire) {
                    closeServer();// 关闭服务器
                }
                System.exit(0);// 退出程序
            }
        });
        
        txt_message.addActionListener(new ActionListener() {//添加监听,监听文本框按回车键按钮事件
            public void actionPerformed(ActionEvent e) {
                send();
            }
        });
        
        button_send.addActionListener(new ActionListener() {//添加监听,监听发送按钮事件
            public void actionPerformed(ActionEvent arg0) {
                send();
            }
        });
        
        button_start.addActionListener(new ActionListener() {//添加监听,监听启动服务器按钮时事件
            public void actionPerformed(ActionEvent e) {
                if (Fire) {
                    JOptionPane.showMessageDialog(frame, "Warning!重复启动","错误", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                int max = 0;//最大人数
                int port = 0;//端口号
                
                try {
                	try {
                        max = Integer.parseInt(txt_max.getText());
                    } catch (Exception e1) {
                        throw new Exception("人数上限不能为空");
                    }
                		if (max <= 0) {
                        throw new Exception("人数上限应为正整数!");
                    }
                	
                	try {
                        port = Integer.parseInt(txt_port.getText());
                    } catch (Exception e1) {
                        throw new Exception("端口号应为整数!");
                    }
                    if (port <= 0) {
                        throw new Exception("端口号应为正整数!");
                    }	
                    
                    serverStart(max, port);
                    contentArea.append("服务器已成功启动!人数上限:" + max + ",端口:" + port+ "\r\n");
                    JOptionPane.showMessageDialog(frame, "服务器成功启动!");
                    button_start.setEnabled(false);//设置按钮不可用
                    txt_max.setEnabled(true);
                    txt_port.setEnabled(true);
                    button_stop.setEnabled(true);//设置按钮可用
                } catch (Exception exc) {
                    JOptionPane.showMessageDialog(frame, exc.getMessage(),"错误", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        // 单击停止服务器按钮时事件
        button_stop.addActionListener(new ActionListener() {//添加监听停止按钮时间
            public void actionPerformed(ActionEvent e) {
                if (!Fire) {
                    JOptionPane.showMessageDialog(frame, "服务器还未启动,无需停止!", "错误",JOptionPane.ERROR_MESSAGE);
                    return;
                }
                try {
                    closeServer();
                    button_start.setEnabled(true);
                    txt_max.setEnabled(true);
                    txt_port.setEnabled(true);
                    button_stop.setEnabled(false);
                    contentArea.append("服务器成功停止!\r\n");
                    JOptionPane.showMessageDialog(frame, "服务器成功停止!");
                } catch (Exception exc) {
                    JOptionPane.showMessageDialog(frame, "停止服务器发生异常!", "错误",JOptionPane.ERROR_MESSAGE);
                }
            }
        });
    }

    // 启动服务器
    public void serverStart(int max, int port) throws java.net.BindException {
        try {
            clients = new ArrayList<ClientThread>();//创建一个客户端集合
            serverSocket = new ServerSocket(port);//套接字创建
            serverThread = new ServerThread(serverSocket, max);//实例化线程
            serverThread.start();//启动线程
            Fire = true;
        } catch (BindException e) {
        	Fire = false;
            throw new BindException("端口号已被占用,请更换!");
        } catch (Exception e1) {
            e1.printStackTrace();
            Fire = false;
            throw new BindException("启动服务器异常!");
        }
    }

   
    @SuppressWarnings("deprecation")
	public void closeServer() { //关闭服务器方法
        try {
            if (serverThread != null)
                serverThread.stop();//关闭线程

            for (int i = clients.size() - 1; i >= 0; i--) {//创建for循环设置i的初始值位客户端数值减一
                // 给所有在线用户发送关闭命令
                clients.get(i).getWriter().println("CLOSE");
                clients.get(i).getWriter().flush();
                // 释放资源
                clients.get(i).stop();// 停止此条为客户端服务的线程
                clients.get(i).reader.close();
                clients.get(i).writer.close();
                clients.get(i).socket.close();
                clients.remove(i);
            }
            if (serverSocket != null) {
                serverSocket.close();//关闭服务器端连接
            }
            listModel.removeAllElements();//清空用户列表
            Fire = false;
        } catch (IOException e) {
            e.printStackTrace();
            Fire = true;
        }
    }
    
    public void sendServerMessage(String message) {// 群发服务器消息
        for (int i = clients.size() - 1; i >= 0; i--) {
            clients.get(i).getWriter().println("服务器:" + message + "(多人发送)");
            clients.get(i).getWriter().flush();
        }
    }

    class ServerThread extends Thread {//服务器线程
        private ServerSocket serverSocket;
        private int max;//人数上限
        
        public ServerThread(ServerSocket serverSocket, int max) {//服务器线程的构造方法
            this.serverSocket = serverSocket;
            this.max = max;
        }

        public void run() {//重写run方法
            while (true) {//不停的等待客户端的链接
                try {
                    Socket socket = serverSocket.accept();//服务器套接字开启监听,返回Socket,抛出异常
                    if (clients.size() == max) {// 如果已达人数上限
                        BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));//将字节流转化成字符流,字节流的来源(套接字socket)
                        PrintWriter w = new PrintWriter(socket.getOutputStream());//将传进来的值写入
                        
                        // 接收客户端的基本用户信息
                        String inf = r.readLine();
                        StringTokenizer st = new StringTokenizer(inf, "@");
                        User user = new User(st.nextToken(), st.nextToken());//获取用户名和IP地址
                        
                        // 反馈连接成功信息
                        w.println("服务器:对不起," + user.getName()+ user.getIp() + ",服务器在线人数已达上限,请稍后尝试连接!");
                        w.flush();//将传进来的值写入
                        r.close();// 释放资源
                        w.close();
                        socket.close();
                        continue;
                    }
                    ClientThread client = new ClientThread(socket);
                    client.start();//开启对此客户端服务的线程
                    clients.add(client);
                    listModel.addElement(client.getUser().getName());//更新在线列表
                    contentArea.append(client.getUser().getName()+ client.getUser().getIp() + "上线!\r\n");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    
    class ClientThread extends Thread {//为一个客户端服务的线程
        private Socket socket;
        private BufferedReader reader;
        private PrintWriter writer;
        private User user;
        
        //get方法
        public BufferedReader getReader() {
            return reader;
        }
        public PrintWriter getWriter() {
            return writer;
        }
        public User getUser() {
            return user;
        }

        public ClientThread(Socket socket) {//客户端线程的构造方法
            try {
                this.socket = socket;
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//将字节流转化成字符流,字节流的来源(套接字socket)
                writer = new PrintWriter(socket.getOutputStream());
                
                // 接收客户端的基本用户信息
                String inf = reader.readLine();//读取客户端字符串
                StringTokenizer st = new StringTokenizer(inf, "@");
                user = new User(st.nextToken(), st.nextToken());
                
                // 反馈连接成功信息
                writer.println(user.getName() + user.getIp() + "与服务器连接成功!");
                writer.flush();
                
                // 反馈当前在线用户信息
                if (clients.size() > 0) {
                    String temp = "";
                    for (int i = clients.size() - 1; i >= 0; i--) {
                        temp += (clients.get(i).getUser().getName() + "/" + clients.get(i).getUser().getIp())+ "@";
                    }
                    writer.println("USERLIST@" + clients.size() + "@" + temp);
                    writer.flush();
                }
                
                // 向所有在线用户发送该用户上线命令
                for (int i = clients.size() - 1; i >= 0; i--) {
                    clients.get(i).getWriter().println("ADD@" + user.getName() + user.getIp());
                    clients.get(i).getWriter().flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @SuppressWarnings("deprecation")
		public void run() {//不断接收客户端的消息,进行处理。重写run方法
            String message = null;
            while (true) {
                try {
                    message = reader.readLine();//接收客户端消息
                    if (message.equals("CLOSE"))//下线命令
                    {
                        contentArea.append(this.getUser().getName()+ this.getUser().getIp() + "下线!\r\n");
                        reader.close();
                        writer.close();
                        socket.close();

                        //向所有在线用户发送该用户的下线命令
                        for (int i = clients.size() - 1; i >= 0; i--) {
                            clients.get(i).getWriter().println(  user.getName());clients.get(i).getWriter().flush();
                        }
                        listModel.removeElement(user.getName());//更新在线列表
                        
                        //删除此条客户端服务线程
                        for (int i = clients.size() - 1; i >= 0; i--) {
                            if (clients.get(i).getUser() == user) {
                                ClientThread temp = clients.get(i);
                                clients.remove(i);//删除此用户的服务线程
                                temp.stop();//停止这条服务线程
                                return;
                            }
                        }
                    } else {
                        dispatcherMessage(message);//转发消息
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // 转发消息
        public void dispatcherMessage(String message) {
            StringTokenizer stringTokenizer = new StringTokenizer(message, "@");
            String source = stringTokenizer.nextToken();
            String owner = stringTokenizer.nextToken();
            String content = stringTokenizer.nextToken();
            message = source + ":" + content;
            contentArea.append(message + "\r\n");
            if (owner.equals("ALL")) {// 群发
                for (int i = clients.size() - 1; i >= 0; i--) {
                    clients.get(i).getWriter().println(message + "(多人发送)");
                    clients.get(i).getWriter().flush();
                }
            }
        }
    }
    public static void main(String[] args) {
        new Sever();//实例化
    }
    
}

user类如下:
User.java

public class User{
    private String name;
    private String ip;
    
    //构造函数
    public User(String name, String ip) {
        this.name = name;
        this.ip = ip;
    }
    
    //get、set方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }
}

上一篇:错误代码大全【100(临时响应)】【200(成功)】【300(已重定向)】【400(请求错误)】【500(服务器错误)】(HTTP协议版本)(二)


下一篇:Dubbo源码解析(二)-以zookeeper为注册中心,深入了解服务调用方消费者注册以及调用