我的程序里面多个客户端在获得服务器更新的在线用户列表时,出现错误。获得列表的思想是:每当一个客户端链接服务器时,客户端会发送自己的登录名给服务器,这时候服务器就同步更新服务器里的在线用户列表(用vector保存),并将更新后的用户列表发送到每个链接服务器的客户端上。 客户端在接受消息的时候,判断接收的是用户列表的时候,便更新客户端本地的在线用户列表(更新后的列表会显示到客户端界面上),但是在显示的时候,只有最近的一个客户端能正常显示在线用户列表,而前面启动的客户端却不能更新在线用户列表。 不知道错误出现在哪儿?我的部分程序如下:服务器端:public final class Server implements Serializable{
    private Hashtable<Socket, ObjectOutputStream> clients;
    private Object clientsLock;
    private static Vector<String> userList; 
    //.........
    //.........
    public void startService() {
        ServerSocket serverSocket=null;
        Socket clientSocket;        try {
            serverSocket=new ServerSocket(port);
            while(true) {
                clientSocket=serverSocket.accept();
                System.out.println("[" + clientSocket.toString() + "] login...");
                new ServerThread(clientSocket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket=null;
                if(serverSocket!= null) {
                    serverSocket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }  
}private class ServerThread extends Thread {
        private Socket clientSocket;        public ServerThread(Socket socket) {
            this.clientSocket=socket;
        }
        
        public void run() {
            ObjectInputStream socketIn=null;
            ObjectOutputStream socketOut=null;
            String logName="";            try {
                socketIn=new ObjectInputStream(this.clientSocket.getInputStream());
                socketOut=new ObjectOutputStream(this.clientSocket.getOutputStream());
                synchronized(logRegServer.this.clientsLock) {
                    if(!logRegServer.this.clients.containsKey(clientSocket)) {
                        logRegServer.this.clients.put(this.clientSocket, socketOut);
                    }
                }
                Object readingObject;
                /**消息标识*/
                String messageType;
                /**消息内容*/
                String messageInformation;
                
                Enumeration<Socket> allKeys;
                Socket otherSocket; /**遍历在线用户时的临时流变量*/
                ObjectOutputStream otherSocketOut;
                
                while ((readingObject=socketIn.readObject())!= null) {
                
                    if (readingObject instanceof String) {
                        messageType=(String)readingObject;
                        if(messageType.equals("NAME")){
                            //这里用户登录后,会发送用户名给服务器,用于更新列表                            
                            logName=(String)socketIn.readObject();
                            
                            messageInformation="System>  "+logName+" has entered.";
                            
                            /**更新在线用户列表*/
                            logRegServer.addUserList(logName);
                           
                            synchronized(logRegServer.this.clientsLock) {
                         allKeys=logRegServer.this.clients.keys();
                        
                         while(allKeys.hasMoreElements()) {
                         otherSocket=allKeys.nextElement();
//                         if(!otherSocket.equals(this.clientSocket)) {
                                    otherSocketOut=logRegServer.this.clients.get(otherSocket);
                                    
                                    /**向各个客户端发送消息标识*/
                                    otherSocketOut.writeObject("LoginExit");                                    /**向在线的用户发送该用户登录的消息*/
                                    otherSocketOut.writeObject(messageInformation);
                                    /**向在线的用户发送更新的在线用户列表*/
                                    otherSocketOut.writeObject(
                                     logRegServer.getUserList());
                                    
                                    otherSocketOut.flush();
//                                    }
                                    Thread.sleep(1);
                         }
                        
                            }                        
                        }else if(messageType.equals("EXIT")){
                         messageInformation="System>  "+logName+" has lefted.";
                         System.out.println(this.clientSocket+" has lefted.");
                        
                                /**更新在线用户列表*/
//                         synchronized(logRegServer.this.userListLock){
//                                     userList.removeElement(logName);
//                         }
                         logRegServer.removeUserList(logName);
                        
                         synchronized(logRegServer.this.clientsLock) {
                         allKeys=logRegServer.this.clients.keys();
                         while(allKeys.hasMoreElements()) {
                         otherSocket=allKeys.nextElement();
                         if(!otherSocket.equals(this.clientSocket)) {
                         otherSocketOut=logRegServer.this.clients.get(otherSocket);
                                    
                         /**发送消息标识*/
                         otherSocketOut.writeObject("LoginExit");
                                    
                         /**向在线的用户发送用户退出的消息*/
                         otherSocketOut.writeObject(messageInformation);
                         /**向在线的用户发送更新的用户列表*/
                         otherSocketOut.writeObject(
                         logRegServer.getUserList());
                                    
                         otherSocketOut.flush();
                         }
                                    Thread.sleep(1);
                         }
//                         }
                         }
                         logRegServer.this.clients.remove(this.clientSocket);
                        }                        
                    }
                    Thread.sleep(1);
                }
            } catch (Exception e) {
                try {
                    synchronized(logRegServer.this.clientsLock) {
                        this.clientSocket.close();
                        logRegServer.this.clients.remove(this.clientSocket);
                    }
                } catch (Exception ee) {
                    ee.printStackTrace();
                }
            }
        }
    }

解决方案 »

  1.   


    客户端:程序是不完整的,因为还有其他代码,太多不好发,不好意思import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    import java.util.Vector;
    import javax.swing.*;
    import javax.swing.border.TitledBorder;public final class GUI extends JFrame {
        private static final long serialVersionUID=2432611980549259658L;
        private static final int serverPort=14444;
        private static final String serverHost="127.0.0.1";    
    /**聊天区用户列表*/
    private JComboBox userL;
    /**在线用户列表*/
    private GUI_userList userList;
    String name="";

        private class ReceiveThread extends Thread {
            private Socket socket=null;
            private ObjectInputStream socketIn=null;
            private ObjectOutputStream socketOut=null;
            private boolean isConnected;        public ReceiveThread() {
                this.isConnected=false;
            }        public synchronized boolean connectToServer(int port, String host) {
                if (!this.isConnected) {
                    try {
                        this.socket=new Socket(host, port);
                        this.socketOut=new ObjectOutputStream(this.socket.getOutputStream());
                        this.socketIn=
                         new ObjectInputStream(this.socket.getInputStream());
                        this.isConnected=true;
                        //发送消息标识“name”和用户登录名name
                        this.sendMessage("NAME");
                        this.sendMessage(name);
                    } catch (Exception e) {
                        this.isConnected=false;
                        e.printStackTrace();
                    }
                }
                return this.isConnected;
            }

            public synchronized boolean sendMessage(String message) {
                boolean retVal=false;            if (this.isConnected) {
                    try {
                        this.socketOut.writeObject(message);
                        this.socketOut.flush();
                        retVal=true;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return retVal;
            }        public void run() {
                try {
                    String messageType;
                    String messageInformation;
                    while (!this.socket.isClosed()) {
                        messageType=(String)this.socketIn.readObject();
                        
                        if (messageType.equals("LoginExit")){
                         /**读取登录或退出的标识*/
                         messageInformation=(String)this.socketIn.readObject();                 /**读取更新后的在线用户列表*/
                     Vector userlist=(Vector)this.socketIn.readObject();
                         /**显示消息*/
                     GUI.this.displayMessage(messageInformation);
                         /**更新用户列表*/
                         GUI.this.updateUserList(userlist);
                        
                        }
                        sleep(1);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    /**增加在线用户列表显示*/
    private JPanel userListPane(){ JPanel p=new JPanel();
    p.setBackground(Color.black);

    p.setLayout(new BorderLayout());

    userL=new JComboBox();
    userList=new GUI_userList();

    /**添加滚动条*/
    JScrollPane pane=new JScrollPane(userList,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    pane.setBackground(Color.black);
    pane.setBorder(BorderFactory.createTitledBorder(null,"Who's online",
             TitledBorder.LEFT,TitledBorder.TOP,this.getFont(),Color.green));

    p.add(pane,BorderLayout.CENTER);
    p.add(userList.getFilterField(),BorderLayout.NORTH);
    p.setBorder(BorderFactory.createTitledBorder(null,"",
             TitledBorder.LEFT,TitledBorder.TOP,this.getFont(),Color.white));

    return p;
    }    private ReceiveThread receiveThread;   protected void displayMessage(String msg) {
            this.chatArea.append(msg + '\n');
        }
        
        public GUI(String nm) {
         this.name=nm;
            this.receiveThread=new ReceiveThread();
        }    protected void updateUserList(Vector UL){
        
         userL.removeAllItems();    
    userL.insertItemAt("All", 0);
    userL.setSelectedIndex(0);

    userList.removeAllItem();

         for(Object ul: UL){
         System.out.println(ul);
         /**更新聊天用户列表*/
         userL.addItem(ul);
        
         /**更新在线用户显示列表*/
         userList.addItem(ul);
         }
        }
      

  2.   

    貌似发帖不能传本地机器上的图片,所以我模拟了下
    用户shimo登录后显示的列表和聊天区域:列表:                         chatArea:
    shimo                      System> shimo has entered.
                  //这里是liguohua登录后,更新的消息,这里消息能正常更新,但是左边的列表却没有更新。
                                   System> liguohua has entered.   
    用户liguohua登录后显示的列表和聊天区域:列表:                         chatArea:
    shimo                      System> liguohua has entered.
    liguohua
      

  3.   

    你的服务端.没有通知客户端.
    最近的更新事实上也没有更新.只是他本身就在这个Vector 中。
    当有一个上线或是下线的时候 你应该把这个新的Vector 发给各个客户端.
      

  4.   

    ............不知道你的错误信息,不好解答,只能给你说下几个注意的地方:
    1、只能唤醒在一个资源队列中的wait线程
    2、一个线程不能访问两个被同步的共享资源~~~~~