发布到多个客户的问题

时间:2012-12-13 23:23:49

标签: java sockets hashmap

嘿伙计们,我最近刚刚收到插座,但遇到了向多个客户发帖的问题。我已经使它多线程处理这个并且我试图保存服务器需要在hashmap中发送的所有客户端数据,但是在循环并添加到hashmap时。它似乎只会增加一个人。继承人代码..

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 个答案:

答案 0 :(得分:1)

name似乎总是为空,因此您继续使用相同的键(null),这可以解释为什么地图中只有一个用户。

另请注意,HashMap不是线程安全的 - 除非您在从线程访问地图时添加某种形式的同步,否则可能会产生令人惊讶的结果。

您可以使用线程安全映射,例如ConcurrentHashMap。