0

やあみんな私は最近ソケットのこつを取得していますが、複数のクライアントへの投稿で問題が発生しました。これを処理するためにマルチスレッド化し、サーバーが送信する必要のあるすべてのクライアントデータをハッシュマップに保持しようとしていますが、サイクリングしてハッシュマップに追加する場合。1人しか追加しないようです。ここにコードがあります。

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) {
            }
        }
    }
}
}
4

1 に答える 1

1

name常にnullのように見えるので、同じキー(null)を使い続けます。これは、マップにユーザーが1人しかいない理由を説明します。

また、HashMapはスレッドセーフではないことに注意してください。スレッドからマップにアクセスするときに何らかの形式の同期を追加しない限り、驚くべき結果が得られる可能性があります。

代わりに、ConcurrentHashMapなどのスレッドセーフマップを使用できます。

于 2012-12-13T23:32:01.770 に答える