2012-12-13 73 views
0

嘿,我最近剛剛得到了一連串的套接字,但遇到了發佈到多個客戶端的問題。我使它成爲多線程來處理這個問題,並且試圖在服務器需要發送到一個散列映射表中的所有客戶端數據中,然而當循環和添加到散列映射時。它似乎只添加一個人。繼承人的代碼..發佈到多個客戶端

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.Iterator; 
import java.util.Map; 

public class HostMain extends Thread { 

/** 
* The set of all names of clients in the chat room. Maintained 
* so that we can check that new clients are not registering name 
* already in use. 
*/ 
private static HashMap<String, ConnectedUsers> users = new HashMap<String, ConnectedUsers>(); 

public HostMain() throws IOException 
{ 

} 

public void run() 
{ 
    try 
    { 
    System.err.println("SERVER:The chat server is running."); 
    ServerSocket listener = new ServerSocket(PORT); 
    System.err.println("SERVER:socket created"); 
    Constants.getInstance().getStatusLabel().setText("Server is running. Join when ready"); 
    try { 
     while (true) { 

      System.err.println("SERVER:New handler being created"); 
      new Handler(listener.accept()).start(); 

     } 
    } finally { 
     listener.close(); 
    } 
    } 
    catch(Exception e) 
    { 
     Constants.getInstance().getStatusLabel().setText("SERVER:A HOST IS ALREADY RUNNING ON THIS PORT!"); 
     System.err.println("SERVER:A HOST IS ALREADY RUNNING ON THIS PORT!"); 
    } 
} 
/** 
* The port that the server listens on. 
*/ 
private static final int PORT = 1337; 




/** 
* The appplication main method, which just listens on a port and 
* spawns handler threads. 
*/ 

/** 
* A handler thread class. Handlers are spawned from the listening 
* loop and are responsible for a dealing with a single client 
* and broadcasting its messages. 
*/ 
private static class Handler extends Thread { 
    private String name; 
    private Socket socket; 
    private BufferedReader in; 
    private PrintWriter out; 
    private ObjectInputStream oin; 
    private ObjectOutputStream oout; 
    /** 
    * Constructs a handler thread, squirreling away the socket. 
    * All the interesting work is done in the run method. 
    */ 
    public Handler(Socket socket) { 
     this.socket = socket; 
    } 

    /** 
    * Services this thread's client by repeatedly requesting a 
    * screen name until a unique one has been submitted, then 
    * acknowledges the name and registers the output stream for 
    * the client in a global set, then repeatedly gets inputs and 
    * broadcasts them. 
    */ 
    public void run() { 
     try { 

      // Create object streams for the socket. 
      in = new BufferedReader(new InputStreamReader(
       socket.getInputStream())); 
      out = new PrintWriter(socket.getOutputStream(), true); 
      oin = new ObjectInputStream(socket.getInputStream()); 
      oout = new ObjectOutputStream(socket.getOutputStream()); 


      //add socket to a list 
      users.put(name,new ConnectedUsers(name,oout)); 
      System.err.println(users.size()); 
      // Accept messages from this client and broadcast them. 
      // Ignore other clients that cannot be broadcasted to. 
      while (true) { 

       Object obj = oin.readObject(); 
       Messages message = (Messages)obj; 
       if(obj.getClass().equals(Messages.class)) 
       { 
        for(Map.Entry<String, ConnectedUsers> entry:users.entrySet()) 
        { 

          ConnectedUsers user = entry.getValue(); 
          user.objectWriter.writeObject(message); 
        } 

       }    

      } 
     } catch (IOException | ClassNotFoundException e) { 
      System.out.println(e); 
     } finally { 
      // This client is going down! Remove its name and its print 
      // writer from the sets, and close its socket. 
      if (name != null) { 
       users.remove(name); 
      } 
      try { 
       socket.close(); 
      } catch (IOException e) { 
      } 
     } 
    } 
} 
} 

回答

1

name似乎總是空,所以你繼續使用相同的密鑰(空),這可以解釋爲什麼只有一個地圖中的用戶。

另請注意,HashMap不是線程安全的 - 除非在從線程訪問地圖時添加某種形式的同步,否則可能會產生令人驚訝的結果。

您可以改爲使用線程安全映射,例如ConcurrentHashMap。

+0

我明白你對這些令人沮喪的結果的意思。謝謝您的幫助! – Raider00321