4lph
4lph

Reputation: 21

How to send a message to a single client when multiple are present

I've been searching for a while, and simply can't find a way to do this. The problem is a multi-user chat client, which works fine. The issue I'm having is being able to send a message from one user to another (client-client), without printing it to the other users.

private static class Handler extends Thread {

    Map<String, Socket> database_UID = new HashMap<String, Socket>();

    private String name;
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;

    public int users;

    private String whisper;
    private String pass;
    private String pass_err = "Unauthorized login attempt";

    public Handler(Socket socket) {
        this.socket = socket;
    }

    public void Append(Socket socket, String name) {
        database_UID.put(name, socket);
        users++;
        System.out.println(ANSI_WHITE + "For reference, the Socket of " + name + " is: " + socket + ANSI_RESET);
        // socket.out.println("Welcome!");
    }

    public void validate(String name_1) {
        // With a given name, will validate Admin and TestBot passwords
        if (name_1.equals("Zach")) {
            out.println("What's your password, admin?");
            try {
                pass = in.readLine();
            } catch (IOException e) {
                System.out.println(e);
            }
            if (pass.equals("1234")) {
                name = ANSI_RED + "ADMIN" + ANSI_RESET + " Zach";
                Append(socket, name);
            } else {
                System.out.println(ANSI_WHITE + "Connection at " + socket.getInetAddress().getHostName() + ":" + socket.getPort() + " Has been terminated for:" + ANSI_RESET + " " + ANSI_RED
                        + pass_err + ANSI_RESET + "\n");
                Removal();
            }
        } else if (name_1.equals("Test")) {
            out.println("What's your password, TestBot?");
            try {
                pass = in.readLine();
            } catch (IOException e) {
                System.out.println(e);
            }
            if (pass.equals("tester")) {
                name = ANSI_RED + "TESTER" + ANSI_RESET + " TestBot";
                Append(socket, name);
            } else {
                System.out.println("Connection at " + socket.getInetAddress().getHostName() + ":" + socket.getPort() + " Has been terminated for:" + ANSI_RESET + " " + ANSI_RED + pass_err
                        + ANSI_RESET + "\n");
                Removal();
            }
        } else {
            Append(socket, name);
        }
    }

    public void Removal() {
        if (name != null) {
            names.remove(name);
        }
        if (out != null) {
            writers.remove(out);
        }
        try {
            socket.close();
        } catch (IOException e) {
        }
    }

    public void run() {
        try {
            System.out.println(ANSI_WHITE + "Connection received from " + socket.getInetAddress().getHostName() + ":" + socket.getPort() + ANSI_RESET);

            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            while (true) {
                out.println("What's your name?");
                name = in.readLine();
                if (name == null) {
                    return;
                }
                if (name.equals("Zach") || name.equals("zach")) {
                    validate("Zach");
                } else if (name.equals("Test") || name.equals("test")) {
                    validate("Test");
                }
                System.out.println(ANSI_WHITE + "Connection at " + socket.getInetAddress().getHostName() + ":" + socket.getPort() + " Has the name " + ANSI_RESET + "'" + name + "'\n");
                if (socket.getInetAddress().equals("localhost")) {
                    System.out.println(ANSI_WHITE + "Connection received locally" + ANSI_RESET);
                }
                synchronized (names) {
                    if (!names.contains(name)) {
                        names.add(name);
                        break;
                    }
                }
            }
            out.println("Your name has been accepted, " + name);
            writers.add(out);

            while (true) {
                String input = in.readLine();
                if (input == null) {
                    return;
                }
                for (PrintWriter writer : writers) {
                    // Allows the user to quit from the server whilst keeping
                    // the terminal open
                    if (input != null) {
                        writer.println("MESSAGE " + name + ": " + input);
                        if (input.equals("quit")) {
                            writer.println(ANSI_RED + "SYSTEM: " + ANSI_RESET + "USER " + name + " IS QUITING");
                            Removal();
                            // The problem is here
                        } else if (input.equals("whisper " + name)) {
                            out.println("Type the message to " + name);
                            whisper = in.readLine();
                            out.println(whisper);
                        } else if (input.equals("help")) {
                            out.println("\n\nHELP MENU\nTo QUIT: Type '" + ANSI_PURPLE + "quit" + ANSI_RESET + "'\nTo WHISPER: Type '" + ANSI_PURPLE + "whisper name_of_user" + ANSI_RESET + "'");
                        } else {
                            writer.println("MESSAGE " + name + ": " + input);
                        }
                    }
                }
            }
        } catch (IOException e) {
            System.out.println(e);
        } finally {
            // Removes the user from the list of names
            Removal();
        }
    }
}

I'm using a Thread, and when the user joins, I add both their name and their Socket to a dictionary

Map<String, Socket> database_UID = new HashMap<String, Socket>();

public void Append(Socket socket, String name) {
    database_UID.put(name, socket);
    users++;
    System.out.println(ANSI_WHITE+"For reference, the Socket of "+name+" is: "+socket+ANSI_RESET);
    //socket.out.println("Welcome!");
}

What I would like to do is, as seen in a comment there, something like socket.out.println(USER'S_MESSAGE);, which obviously doesn't work. If it's relevant, the client's socket is being added as

public Handler(Socket socket) {
    this.socket = socket;
}

The tl;dr version:

Person A to whole server: Hi!

Person B specifically to Person A: Hi!

EDIT: Included above is the entire Thread. The for(PrintWriter writer : writers) { is where it would go, under 'whisper'.

Upvotes: 0

Views: 142

Answers (1)

Vikash Kesarwani
Vikash Kesarwani

Reputation: 850

Follow these steps

  1. Create another thread on the server to listen to the messages coming from clients.
  2. Send message from client A to server
  3. Check the destination client (which can be part of you message sent from client to server)
  4. Send the message from server to the destined client.

Upvotes: 1

Related Questions