Java-向所有客户端发送消息

Java-向所有客户端发送消息,java,Java,我正在使用套接字服务器和线程创建聊天服务器。在我的服务器ChatServer.java、ThreadedServer.java和Main.java中有3个类。我的客户端有2个ChatClient.java,Main.java。我需要这样做,当消息从客户端发送到服务器时,服务器会将消息发送到所有客户端 ChatServer.java package server; import java.io.*; import java.net.*; public class ChatServer {

我正在使用套接字服务器和线程创建聊天服务器。在我的服务器ChatServer.java、ThreadedServer.java和Main.java中有3个类。我的客户端有2个ChatClient.java,Main.java。我需要这样做,当消息从客户端发送到服务器时,服务器会将消息发送到所有客户端

ChatServer.java

package server;

import java.io.*;
import java.net.*;

public class ChatServer {
    protected Socket s;
    protected Socket ss;
    public ChatServer() {
        try {
             ServerSocket ss=new ServerSocket(6969);
             Runtime.getRuntime().addShutdownHook(new Thread() {
                 public void main(String []args) throws IOException {
                    ss.close();
                }
            });
            while (true) {
                Socket s =ss.accept();
                new ThreadedServer(s).start();
            }
        }catch(Exception e) {
            System.out.println(e);
        }
        new ThreadedServer(s).start();
      }
}
package server;

import java.io.*;
import java.net.*;

public class ThreadedServer extends Thread{
    protected Socket socket;

    public ThreadedServer(Socket clientSocket) {
        this.socket = clientSocket;
    }

    public void run() {
        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            while (true) {
                String str=(String)dis.readUTF();
                String remote = socket.getInetAddress().toString();
                String newmes = remote + ": " + str;
                dos.writeUTF(newmes);
                System.out.println(newmes);
                if (str.toUpperCase() == "QUIT") {
                    socket.close();
                    break;
                }else if (str.toUpperCase() == "EXIT") {
                    socket.close();
                    break;
                }
            }
        }catch(Exception e) {
            System.out.println(e);
        }
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;

/**
 * A multithreaded chat room server.  When a client connects the
 * server requests a screen name by sending the client the
 * text "SUBMITNAME", and keeps requesting a name until
 * a unique one is received.  After a client submits a unique
 * name, the server acknowledges with "NAMEACCEPTED".  Then
 * all messages from that client will be broadcast to all other
 * clients that have submitted a unique screen name.  The
 * broadcast messages are prefixed with "MESSAGE ".
 *
 * Because this is just a teaching example to illustrate a simple
 * chat server, there are a few features that have been left out.
 * Two are very useful and belong in production code:
 *
 *     1. The protocol should be enhanced so that the client can
 *        send clean disconnect messages to the server.
 *
 *     2. The server should do some logging.
 */
public class ChatServer {

    /**
     * The port that the server listens on.
     */
    private static final int PORT = 9001;

    /**
     * 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 HashSet<String> names = new HashSet<String>();

    /**
     * The set of all the print writers for all the clients.  This
     * set is kept so we can easily broadcast messages.
     */
    private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();

    /**
     * The appplication main method, which just listens on a port and
     * spawns handler threads.
     */
    public static void main(String[] args) throws Exception {
    System.out.println("The chat server is running.");
    ServerSocket listener = new ServerSocket(PORT);
    try {
        while (true) {
        new Handler(listener.accept()).start();
        }
    } finally {
        listener.close();
    }
    }

    /**
     * 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;

    /**
         * 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 character streams for the socket.
        in = new BufferedReader(new InputStreamReader(
                                  socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);

        // Request a name from this client.  Keep requesting until
        // a name is submitted that is not already used.  Note that
        // checking for the existence of a name and adding the name
        // must be done while locking the set of names.
        while (true) {
            out.println("SUBMITNAME");
            name = in.readLine();
            if (name == null) {
            return;
            }
            synchronized (names) {
            if (!names.contains(name)) {
                names.add(name);
                break;
            }
            }
        }

        // Now that a successful name has been chosen, add the
        // socket's print writer to the set of all writers so
        // this client can receive broadcast messages.
        out.println("NAMEACCEPTED");
        writers.add(out);

        // Accept messages from this client and broadcast them.
        // Ignore other clients that cannot be broadcasted to.
        while (true) {
            String input = in.readLine();
            if (input == null) {
            return;
            }
            for (PrintWriter writer : writers) {
            writer.println("MESSAGE " + name + ": " + input);
            }
        }
        } catch (IOException 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) {
            names.remove(name);
        }
        if (out != null) {
            writers.remove(out);
        }
        try {
            socket.close();
        } catch (IOException e) {
        }
        }
    }
    }
}
ThreadedServer.java

package server;

import java.io.*;
import java.net.*;

public class ChatServer {
    protected Socket s;
    protected Socket ss;
    public ChatServer() {
        try {
             ServerSocket ss=new ServerSocket(6969);
             Runtime.getRuntime().addShutdownHook(new Thread() {
                 public void main(String []args) throws IOException {
                    ss.close();
                }
            });
            while (true) {
                Socket s =ss.accept();
                new ThreadedServer(s).start();
            }
        }catch(Exception e) {
            System.out.println(e);
        }
        new ThreadedServer(s).start();
      }
}
package server;

import java.io.*;
import java.net.*;

public class ThreadedServer extends Thread{
    protected Socket socket;

    public ThreadedServer(Socket clientSocket) {
        this.socket = clientSocket;
    }

    public void run() {
        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            while (true) {
                String str=(String)dis.readUTF();
                String remote = socket.getInetAddress().toString();
                String newmes = remote + ": " + str;
                dos.writeUTF(newmes);
                System.out.println(newmes);
                if (str.toUpperCase() == "QUIT") {
                    socket.close();
                    break;
                }else if (str.toUpperCase() == "EXIT") {
                    socket.close();
                    break;
                }
            }
        }catch(Exception e) {
            System.out.println(e);
        }
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;

/**
 * A multithreaded chat room server.  When a client connects the
 * server requests a screen name by sending the client the
 * text "SUBMITNAME", and keeps requesting a name until
 * a unique one is received.  After a client submits a unique
 * name, the server acknowledges with "NAMEACCEPTED".  Then
 * all messages from that client will be broadcast to all other
 * clients that have submitted a unique screen name.  The
 * broadcast messages are prefixed with "MESSAGE ".
 *
 * Because this is just a teaching example to illustrate a simple
 * chat server, there are a few features that have been left out.
 * Two are very useful and belong in production code:
 *
 *     1. The protocol should be enhanced so that the client can
 *        send clean disconnect messages to the server.
 *
 *     2. The server should do some logging.
 */
public class ChatServer {

    /**
     * The port that the server listens on.
     */
    private static final int PORT = 9001;

    /**
     * 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 HashSet<String> names = new HashSet<String>();

    /**
     * The set of all the print writers for all the clients.  This
     * set is kept so we can easily broadcast messages.
     */
    private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();

    /**
     * The appplication main method, which just listens on a port and
     * spawns handler threads.
     */
    public static void main(String[] args) throws Exception {
    System.out.println("The chat server is running.");
    ServerSocket listener = new ServerSocket(PORT);
    try {
        while (true) {
        new Handler(listener.accept()).start();
        }
    } finally {
        listener.close();
    }
    }

    /**
     * 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;

    /**
         * 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 character streams for the socket.
        in = new BufferedReader(new InputStreamReader(
                                  socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);

        // Request a name from this client.  Keep requesting until
        // a name is submitted that is not already used.  Note that
        // checking for the existence of a name and adding the name
        // must be done while locking the set of names.
        while (true) {
            out.println("SUBMITNAME");
            name = in.readLine();
            if (name == null) {
            return;
            }
            synchronized (names) {
            if (!names.contains(name)) {
                names.add(name);
                break;
            }
            }
        }

        // Now that a successful name has been chosen, add the
        // socket's print writer to the set of all writers so
        // this client can receive broadcast messages.
        out.println("NAMEACCEPTED");
        writers.add(out);

        // Accept messages from this client and broadcast them.
        // Ignore other clients that cannot be broadcasted to.
        while (true) {
            String input = in.readLine();
            if (input == null) {
            return;
            }
            for (PrintWriter writer : writers) {
            writer.println("MESSAGE " + name + ": " + input);
            }
        }
        } catch (IOException 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) {
            names.remove(name);
        }
        if (out != null) {
            writers.remove(out);
        }
        try {
            socket.close();
        } catch (IOException e) {
        }
        }
    }
    }
}
Main.java(服务器) 包服务器

public class Main {
    public static void main(String[] args) {
        ChatServer chat = new ChatServer();
    }
}
下面是Client.java的

ChatClient.java 包客户端

import java.io.*;
import java.net.*;

public class ChatClient {

    public ChatClient() {
        try {
            Socket s = new Socket("10.4.27.29",6969);
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void main(String []args) throws IOException {
                    s.close();
                }
            });
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            DataInputStream dis = new DataInputStream(s.getInputStream());
            while (true) {
                String message = System.console().readLine();
                dos.writeUTF(message);
                System.out.println(dis.readUTF());
            }
        }catch(Exception e) {
             System.out.println(e);
        }
    }
}
Main.java(客户端)

求求你,任何帮助都会令人惊讶的


此外,如果有任何想法能让这更美好,我们将不胜感激。谢谢

试着运行这个。这是我做的一个有效的

ChatServer.java

package server;

import java.io.*;
import java.net.*;

public class ChatServer {
    protected Socket s;
    protected Socket ss;
    public ChatServer() {
        try {
             ServerSocket ss=new ServerSocket(6969);
             Runtime.getRuntime().addShutdownHook(new Thread() {
                 public void main(String []args) throws IOException {
                    ss.close();
                }
            });
            while (true) {
                Socket s =ss.accept();
                new ThreadedServer(s).start();
            }
        }catch(Exception e) {
            System.out.println(e);
        }
        new ThreadedServer(s).start();
      }
}
package server;

import java.io.*;
import java.net.*;

public class ThreadedServer extends Thread{
    protected Socket socket;

    public ThreadedServer(Socket clientSocket) {
        this.socket = clientSocket;
    }

    public void run() {
        try {
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            while (true) {
                String str=(String)dis.readUTF();
                String remote = socket.getInetAddress().toString();
                String newmes = remote + ": " + str;
                dos.writeUTF(newmes);
                System.out.println(newmes);
                if (str.toUpperCase() == "QUIT") {
                    socket.close();
                    break;
                }else if (str.toUpperCase() == "EXIT") {
                    socket.close();
                    break;
                }
            }
        }catch(Exception e) {
            System.out.println(e);
        }
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;

/**
 * A multithreaded chat room server.  When a client connects the
 * server requests a screen name by sending the client the
 * text "SUBMITNAME", and keeps requesting a name until
 * a unique one is received.  After a client submits a unique
 * name, the server acknowledges with "NAMEACCEPTED".  Then
 * all messages from that client will be broadcast to all other
 * clients that have submitted a unique screen name.  The
 * broadcast messages are prefixed with "MESSAGE ".
 *
 * Because this is just a teaching example to illustrate a simple
 * chat server, there are a few features that have been left out.
 * Two are very useful and belong in production code:
 *
 *     1. The protocol should be enhanced so that the client can
 *        send clean disconnect messages to the server.
 *
 *     2. The server should do some logging.
 */
public class ChatServer {

    /**
     * The port that the server listens on.
     */
    private static final int PORT = 9001;

    /**
     * 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 HashSet<String> names = new HashSet<String>();

    /**
     * The set of all the print writers for all the clients.  This
     * set is kept so we can easily broadcast messages.
     */
    private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();

    /**
     * The appplication main method, which just listens on a port and
     * spawns handler threads.
     */
    public static void main(String[] args) throws Exception {
    System.out.println("The chat server is running.");
    ServerSocket listener = new ServerSocket(PORT);
    try {
        while (true) {
        new Handler(listener.accept()).start();
        }
    } finally {
        listener.close();
    }
    }

    /**
     * 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;

    /**
         * 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 character streams for the socket.
        in = new BufferedReader(new InputStreamReader(
                                  socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);

        // Request a name from this client.  Keep requesting until
        // a name is submitted that is not already used.  Note that
        // checking for the existence of a name and adding the name
        // must be done while locking the set of names.
        while (true) {
            out.println("SUBMITNAME");
            name = in.readLine();
            if (name == null) {
            return;
            }
            synchronized (names) {
            if (!names.contains(name)) {
                names.add(name);
                break;
            }
            }
        }

        // Now that a successful name has been chosen, add the
        // socket's print writer to the set of all writers so
        // this client can receive broadcast messages.
        out.println("NAMEACCEPTED");
        writers.add(out);

        // Accept messages from this client and broadcast them.
        // Ignore other clients that cannot be broadcasted to.
        while (true) {
            String input = in.readLine();
            if (input == null) {
            return;
            }
            for (PrintWriter writer : writers) {
            writer.println("MESSAGE " + name + ": " + input);
            }
        }
        } catch (IOException 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) {
            names.remove(name);
        }
        if (out != null) {
            writers.remove(out);
        }
        try {
            socket.close();
        } catch (IOException e) {
        }
        }
    }
    }
}

关于“让这更美好”。考虑使用非阻塞套接字IO。关于将消息发送到所有客户端:在服务器上保留一组套接字,并将消息发送到每个已连接的套接字(但从发送的套接字除外)。我正在寻找将其添加到代码中的方法。这听起来可能有些刺耳,但我希望它能与我的代码一起工作,因为我试图从头开始构建,但无法理解这个概念。那么看看我的示例,然后实现与您类似的逻辑。您不需要使用我的全部代码,但是有一个您想要的“工作示例”会有所帮助。我在我的客户机上使用JavaSwing,但这并不意味着您必须这样做。