java - 当存在多个客户端时如何向单个客户端发送消息

标签 java sockets server

我已经搜索了一段时间了,但就是找不到方法来做到这一点。问题是多用户聊天客户端,它工作正常。我遇到的问题是能够从一个用户向另一个用户发送消息(客户端-客户端),而不将其打印给其他用户。

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();
        }
    }
}

我正在使用线程,当用户加入时,我将他们的名字和套接字添加到字典中

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!");
}

我想做的是,正如评论中所见,类似 socket.out.println(USER'S_MESSAGE); 的东西,这显然不起作用。 如果相关,客户端的套接字将被添加为

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

tl;dr 版本:

A对整个服务器:嗨!

B 专门对 A 说:嗨!

编辑:上面包含的是整个线程。 for(PrintWriter writer : writers) { 就是它所在的位置,位于“whisper”下。

最佳答案

按照以下步骤操作

  1. 在服务器上创建另一个线程来监听来自客户端的消息。
  2. 从客户端 A 向服务器发送消息
  3. 检查目标客户端(可以是从客户端发送到服务器的消息的一部分)
  4. 将消息从服​​务器发送到目标客户端。

关于java - 当存在多个客户端时如何向单个客户端发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31085455/

相关文章:

java - ServerSocket close 方法不释放端口

c# - Socket c# 通过互联网聊天?

在单个端口上配置多个 UDP 套接字

node.js - socket io 获取已断开连接的套接字的 id

linux - Apache DirectoryRoot 配置?

java - 当您拥有 Spring 和 Dagger 时,为什么要使用/开发 Guice?

java - 如何使用 hibernate JPA 注释连接两列

java - 如何通过单元测试测试时区方法?

java - 如何从 DirectoryStream 制作流

java - 如何在非 GUI 服务器环境中运行 libGDX 应用程序?