这两天写JAVA实现局域网聊天室,在添加用户列表时遇到了问题
思路是:点击“登录”时发送用户信息,前面加上“!@#$”作标识符,服务器读到它就知道是用户信息,调用tellUserInfo方法
点击“发送”时,把聊天信息发送给服务器,服务器读到它就调用tellEveryone方法下面实现用户列表的代码,只有最后一个客户端的用户列表是正确的
看不出哪里的问题,帮忙看看,先谢啦import java.io.*;
import java.net.*;
import java.util.*;public class ChatServer {
    // 定义一个ArrayList,存放所有客户端对应的输出流
    private ArrayList<PrintWriter> writers;
    PrintWriter writer;
    BufferedReader reader;
    String clientName,clientIP,clientInfo;
    private ArrayList<String> userList = new ArrayList<String>(); // 存储用户的信息 clientInfo    public void go() {
        // 用一个ArrayList存放与所有客户端对应的输出流
        writers = new ArrayList<PrintWriter>();
        try {
            // 定义一个ServerSocket对象
            ServerSocket serverSock = new ServerSocket(6000);            while(true) {
                Socket socket = serverSock.accept();
               
                PrintWriter writer = new PrintWriter(socket.getOutputStream());
                writers.add(writer);                // 对于每个客户端,生成一个线程对象,来做专门的处理
                Thread t = new Thread(new ClientHandler(socket));
                t.start();            }
        }catch(Exception ex) {
            ex.printStackTrace();
        }
    }    // 定义一个内部类,实现Runnable接口,以便用线程进行处理
    public class ClientHandler implements Runnable {
        // 字段定义        Socket socket;
        public ClientHandler(Socket socket) {
            try {
                // 在构造器中指定针对客户端的输入流
                this.socket = socket;
                reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
                
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }        // 实现run方法
        public void run() {
            String chatMsg = "",userInfo = "",str = "";
            try {
str = reader.readLine();
if(str.equals("!@#$")){
userInfo = reader.readLine();
userList.add(userInfo);
    tellUserInfo();
}            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }    // 向所有客户端发送信息
    public void tellEveryone(String message) {
        for(PrintWriter pt: writers){
            pt.println(message);
            pt.flush();
        }
    }    public void tellUserInfo(){
        Collections.sort(userList);
        for( PrintWriter pt: writers ){
pt.println("!@#$");
            for (int i = 0; i < userList.size(); i++) {
                pt.println(userList.get(i));
            }
            pt.flush();
        }
       
    }    public static void main(String[] args) {
        new ChatServer().go(); // 服务器启动
    }}

解决方案 »

  1.   

    下面是客户端的代码import java.io.*;
    import java.net.*;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;public class ChatClient {
        JTextField jtf_name,jtf_ip; // LoginGUI组件
        JTextField jtf_filePath,jtf_userSlectForFileSend;  // FileSendGUI组件
        JTextArea jta_incoming = new JTextArea(),
      jta_outgoing = new JTextArea(),
      jta_userInfo = new JTextArea();  // ClientGUI组件
        BufferedReader reader; // 缓冲区流(用来读取文本信息)
        PrintWriter writer; // 输出文本信息的流
        Socket socket; // socket
        String clientName,clientIP,clientInfo;  // 客户端的名字和它设置的服务器ip地址
        LoginGUI loginGUI;  //构建登陆界面
        ClientGUI clientGUI;  //构建客户端界面
        
        public void go() {
            // 用Swing构建一个客户端的界面
            loginGUI = new LoginGUI();
            
    // 调用自定义的setUpNetworking方法设定网络连接
            setUpNetworking();         // 开启一个线程来处理信息的读取   start后开始等待从服务器返回的流
            Thread readerThread = new Thread(new msgReader());
            readerThread.start();    }    private void setUpNetworking() {
            try {
                // 设定网络连接,准备好用于输入、输出文本信息的“流对象”
                socket = new Socket(clientIP,6000);
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                writer = new PrintWriter(socket.getOutputStream());
                
                System.out.println("网络连接建立完毕!");        } catch (IOException ex) {
                ex.printStackTrace();
            }
        }    // 实现Runnable接口,以便用线程进行处理
        public class msgReader implements Runnable {
            // 实现run方法
            public void run() {
                String userInfo = "",chatMsg = "",str = "";
                try {
    str = reader.readLine();
    if(str.equals("!@#$")){
    jta_userInfo.setText("");
    while((userInfo = reader.readLine()) != null){
    jta_userInfo.append(userInfo + "\n");
    }
    }
                    
                } catch(Exception ex) {
                    ex.printStackTrace();
                }
            }
        }    public class jb_sendButtonListener implements ActionListener {
            // 实现actionPerformed方法
            public void actionPerformed(ActionEvent ae) {
                try {
                    // 当用户按下“发送”按钮时,就把文本框中的文本写到网络流中
                    writer.println(clientName + "说:\n"  + jta_outgoing.getText());
                    writer.flush();            } catch(Exception ex) {
                    ex.printStackTrace();
                }
                // 清空文本框,以便录入新的信息
                jta_outgoing.setText("");
            }
        }       public class jb_loginListener implements ActionListener{
            public void actionPerformed(ActionEvent e){
                clientName = jtf_name.getText();
                clientIP = socket.getLocalAddress().toString();
                clientInfo = clientName + clientIP;
                
    writer.println("!@#$");
                writer.println(clientInfo);
                writer.flush();            loginGUI.setVisible(false);
                clientGUI = new ClientGUI();        }
        }
      

  2.   

    客户端的代码续:  
      public class ClientGUI extends JFrame{        JPanel jp1,jp2,jp3,jp4,jp5,jp6,jp7,jp8;
            JScrollPane jp9,jp10,jp11;
            JButton jb_send,jb_quit,jb_file,jb_pic,jb_chat;
            JLabel jl;        public ClientGUI(){
                this.setTitle("局域网聊天室");
                jp1 = new JPanel();
                jp2 = new JPanel();
                jp3 = new JPanel();
                jp4 = new JPanel();
                jp5 = new JPanel();
                jp6 = new JPanel();
                jp7 = new JPanel();
                jp8 = new JPanel();            jp1.setLayout(new BorderLayout());
                jp2.setLayout(new BorderLayout());
                jp3.setLayout(new BorderLayout());
                jp4.setLayout(new BorderLayout());
                jp8.setLayout(new BorderLayout());
                jp5.setLayout(new FlowLayout(FlowLayout.RIGHT));
                jp6.setLayout(new FlowLayout(FlowLayout.RIGHT));            jta_incoming = new JTextArea();
                jta_outgoing = new JTextArea(4,28);
                //jta_userInfo = new JTextArea();
                jta_incoming.setEditable(false);
                jta_userInfo.setEditable(false);            jp9 = new JScrollPane(jta_incoming);
                jp10 = new JScrollPane(jta_outgoing);
                jp11 = new JScrollPane(jta_userInfo);
             jb_send = new JButton("发送");
                jb_quit = new JButton("关闭");
             jb_file = new JButton("传送文件");
                jb_pic = new JButton("接收文件");
                jb_chat = new JButton("私聊");
                jb_send.setSize(80,20);
                jb_quit.setSize(80,20);
                jb_file.setSize(80,20);
                jb_pic.setSize(80,20);            //发送按钮注册监听器
                jb_send.addActionListener(new jb_sendButtonListener());
                //文件发送按钮注册监听器
                //jb_file.addActionListener(new jb_fileSendButtonListener());
                //私聊按钮注册监听器
                //jb_chat.addActionListener(new jb_chatButtonListener());     jl = new JLabel("用户列表                            ");            jp2.add(jp9,BorderLayout.CENTER);
                jp2.add(jp3,BorderLayout.SOUTH);            jp3.add(jp5,BorderLayout.NORTH);
                jp3.add(jp10,BorderLayout.CENTER);
                jp3.add(jp6,BorderLayout.SOUTH);         jp5.add(jb_file);
                jp5.add(jb_pic);
                jp5.add(jb_chat);         jp6.add(jb_send);
                jp6.add(jb_quit);         jp8.add(jl,BorderLayout.NORTH);
                jp8.add(jp11,BorderLayout.CENTER);            jp4.add(jp8,BorderLayout.CENTER);
                jp4.add(jp7,BorderLayout.WEST);            jp1.add(jp2,BorderLayout.CENTER);
                jp1.add(jp4,BorderLayout.EAST);         this.add(jp1);            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                this.setBounds(200,100,600,500);
                this.setVisible(true);
            }    }    public class FileSendGUI extends JFrame{
            JPanel jp1,jp2,jp3,jp4; GridLayout gl;
            JLabel jl1,jl2;
            JButton jb_send,jb_quit;        public FileSendGUI(){
                jp1 = new JPanel();  gl = new GridLayout(3,1);
    jp1.setLayout(gl);
                jp2 = new JPanel();  jp3 = new JPanel();  jp4 = new JPanel();
                jp1.add(jp2);  jp1.add(jp3); jp1.add(jp4);            jl1 = new JLabel("输入文件完整路径:");  jl2 = new JLabel("输入用户名(ALL为所有人):");
                jtf_filePath = new JTextField(20);  jtf_userSlectForFileSend = new JTextField(20);
                jb_send = new JButton("发送");  jb_quit = new JButton("取消");            jp2.add(jl1);  jp2.add(jtf_filePath);
                jp3.add(jl2);  jp3.add(jtf_userSlectForFileSend);
                jp4.add(jb_send);  jp4.add(jb_quit); this.add(jp1); this.setBounds(300,250,300,200);
    this.setVisible(true);        }
        }    public class ChatSelectGUI extends JFrame{
            JPanel jp1,jp2,jp3,jp4; GridLayout gl;
            JLabel jl1,jl2;
            JTextField jtf1,jtf2;
            JButton jb_send,jb_quit;        public ChatSelectGUI(){
                jp1 = new JPanel();  gl = new GridLayout(2,1);
    jp1.setLayout(gl);
                jp2 = new JPanel();  jp3 = new JPanel();
                jp1.add(jp2);  jp1.add(jp3);            jl1 = new JLabel("输入对方用户名:"); jtf1 = new JTextField(16);
                jb_send = new JButton("确定");  jb_quit = new JButton("取消");            jp2.add(jl1);  jp2.add(jtf1);
                jp3.add(jb_send);  jp3.add(jb_quit); this.add(jp1); this.setBounds(300,250,300,200);
    this.setVisible(true);
            }    }    public class LoginGUI extends JFrame{
            JPanel jp1,jp2,jp3,jp4;  GridLayout gridLayout;
            JLabel jl1,jl2;
            JButton jb_login,jb_quit;
            public LoginGUI(){
                jp1 = new JPanel();  jp2 = new JPanel();  jp3 = new JPanel();
                jp4 = new JPanel();  gridLayout = new GridLayout(3,1);
                jl1 = new JLabel("输入你的昵称:");  jl2 = new JLabel("服务器的地址:");
                jtf_name = new JTextField(10);jtf_ip = new JTextField(10);
                jb_login = new JButton("登录");  jb_quit = new JButton("取消");
                jp1.setLayout(gridLayout);
                this.getContentPane().add(jp1);
                jp1.add(jp2);jp1.add(jp3);jp1.add(jp4);
                jp2.add(jl1);jp2.add(jtf_name);
                jp3.add(jl2);jp3.add(jtf_ip);
                jp4.add(jb_login);jp4.add(jb_quit);            //登录按钮注册监听器,启动客户端界面
                jb_login.addActionListener(new jb_loginListener());            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
                this.setVisible(true);
                this.setBounds(350, 250, 300, 200);
            }
        }    public static void main(String[] args){
            ChatClient client = new ChatClient();
            client.go();
        }
    }
      

  3.   

    bu cuo bu cuo 
    xie xie lou zu le
      

  4.   


    use// 定义一个内部类,实现Runnable接口,以便用线程进行处理 
        public class ClientHandler implements Runnable { 
            // 字段定义         Socket socket; 
            public ClientHandler(Socket socket) { 
                try { 
                    // 在构造器中指定针对客户端的输入流 
                    this.socket = socket; 
                    reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); 
                    
                } catch(Exception ex) { 
                    ex.printStackTrace(); 
                } 
            }         // 实现run方法 
            public void run() { 
                String chatMsg = "",userInfo = "",str = ""; 
                try { 
    str = reader.readLine(); 
    if(str.equals("!@#$")){ 
    userInfo = reader.readLine(); //问题
    userList.add(userInfo); //问题
        tellUserInfo(); //问题
    }             } catch(Exception ex) { 
                    ex.printStackTrace(); 
                } 
            } 
        } 
    rList是动态增加的,例如第一个客户端登录,你只把第一个客户信息发给他
    第二个客户端登录的时候,你发送的是第一个和第二个的信息,以此类推,只有最后的客户端
    用户列表是正确的
    可以这样做:
    在所有的客户端都连接了之后,在发送用户列表,
    或者没隔几秒钟发送用户列表,
      

  5.   

    我始终没看见你的tellEveryone方法在哪里被调用了