如何在Java套接字编程中获取客户端(当前正在发送消息)名称

时间:2019-03-09 14:38:41

标签: java sockets jframe

我有此代码示例,试图获取当前主机的详细信息。 我需要获取当前主机的JFrame标题(在其中设置了主机名)

之所以这样做,是因为我修改了程序,仅向其他客户端发送私人消息,因此该消息不会成为广播消息。

我使用了关键字“ 仅B ”,当您键入并发送该关键字时,只有名称为B的客户端/主机会收到此消息。

但是问题是消息没有显示在发送者的屏幕上,而是仅显示在接收者的屏幕上(即客户端“ B”)

我需要获取JFrame标题值(在其中设置了客户端的名称),以便我也可以在发件人的屏幕上显示消息。

还是我必须使用另一种方法?请让我知道。如何在Java套接字编程中获取当前主机的(发件人)名称?

这是我的ChatServer.java

import java.awt.Frame;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

/**
 * 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>();
    private static HashSet<String> passedNames = 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>(); 
    private static HashMap<String,PrintWriter> namesWithWriter = new HashMap<String,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) {
                Socket socket  = listener.accept();
                Thread handlerThread = new Thread(new Handler(socket));
                handlerThread.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 implements Runnable {
        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;
                    }

                    // TODO: Add code to ensure the thread safety of the
                    // the shared variable 'names'
                    synchronized (names) {                                           
                        if (!names.contains(name)) {                            
                            names.add(name);
                            passedNames.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);

                namesWithWriter.put(name,out);


                // TODO: You may have to add some code here to broadcast all clients the new
                // client's name for the task 9 on the lab sheet. 

                for(String key : namesWithWriter.keySet()){
                    if(key.equals(name)){
                        for(String name : names){
                            namesWithWriter.get(key).println("NEWNAME"+name);
                        }
                    }else{
                        namesWithWriter.get(key).println("NAME"+name);
                    }
                }


                // Accept messages from this client and broadcast them.
                // Ignore other clients that cannot be broadcasted to.






                while (true) {
                    String inputMessage = in.readLine();

                    if(inputMessage.startsWith("only") && inputMessage.trim().length()>4){
                        System.out.println("Specific  User");
                        if (inputMessage == null) {
                            return;
                        }

                        System.out.println("Passed Names: "+passedNames);
                        String nameInTheInput = inputMessage.substring(5);

                        //System.out.println("Name in the Input "+nameInTheInput);


                        for(String key : namesWithWriter.keySet()) {
                            if(nameInTheInput.equalsIgnoreCase(key)) {
                                System.out.println("Send");
                                namesWithWriter.get(key).println("MESSAGE " + name + ": " + inputMessage+ " (only you and "+name+" can see this message)");

                                String hostName = socket.getInputStream().toString();
                                System.out.println("hostname is: "+hostName);

                            }else {

                                System.out.println("Don't send");
                            }
                        }


                    }else if(inputMessage.startsWith("all") && inputMessage.trim().length()>=3){ //to all the clients
                        System.out.println("All  User");
                        for (PrintWriter writer : writers) {                            
                            writer.println("MESSAGE " + name + ": " + inputMessage);
                        }
                    }else{
                        System.out.println("No  User");
                        //passedNames.add(inputMessage);
                    }

                    // TODO: Add code to send a message to a specific client and not
                    // all clients. You may have to use a HashMap to store the sockets along 
                    // with the chat client names                                                                             
                }
            }// TODO: Handle the SocketException here to handle a client closing the socket
            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) {
                }
            }
        }
    }
}

这是我的* ChatClient.java **

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * A simple Swing-based client for the chat server.  Graphically
 * it is a frame with a text field for entering messages and a
 * textarea to see the whole dialog.
 *
 * The client follows the Chat Protocol which is as follows.
 * When the server sends "SUBMITNAME" the client replies with the
 * desired screen name.  The server will keep sending "SUBMITNAME"
 * requests as long as the client submits screen names that are
 * already in use.  When the server sends a line beginning
 * with "NAMEACCEPTED" the client is now allowed to start
 * sending the server arbitrary strings to be broadcast to all
 * chatters connected to the server.  When the server sends a
 * line beginning with "MESSAGE " then all characters following
 * this string should be displayed in its message area.
 */
public class ChatClient {

    BufferedReader in;
    PrintWriter out;
    JFrame frame = new JFrame();    
    JTextField textField = new JTextField(40);
    JTextArea messageArea = new JTextArea(8, 40);
    // TODO: Add a list box

    /**
     * Constructs the client by laying out the GUI and registering a
     * listener with the textfield so that pressing Return in the
     * listener sends the textfield contents to the server.  Note
     * however that the textfield is initially NOT editable, and
     * only becomes editable AFTER the client receives the NAMEACCEPTED
     * message from the server.
     */
    public ChatClient() {

        // Layout GUI
        textField.setEditable(false);
        messageArea.setEditable(false);
        frame.getContentPane().add(textField, "North");
        frame.getContentPane().add(new JScrollPane(messageArea), "Center");
        frame.pack();


        // TODO: You may have to edit this event handler to handle point to point messaging,
        // where one client can send a message to a specific client. You can add some header to 
        // the message to identify the recipient. You can get the receipient name from the listbox.
        textField.addActionListener(new ActionListener() {
            /**
             * Responds to pressing the enter key in the textfield by sending
             * the contents of the text field to the server.    Then clear
             * the text area in preparation for the next message.
             */
            public void actionPerformed(ActionEvent e) {
                out.println(textField.getText());
                textField.setText("");
            }
        });


    }

    /**
     * Prompt for and return the address of the server.
     */
    private String getServerAddress() {
        return JOptionPane.showInputDialog(
            frame,
            "Enter IP Address of the Server:",
            "Welcome to the Chatter",
            JOptionPane.QUESTION_MESSAGE);
    }

    /**
     * Prompt for and return the desired screen name.
     */
    private String getName() {
        String name = JOptionPane.showInputDialog(
                frame,
                "Choose a screen name:",
                "Screen name selection",
                JOptionPane.PLAIN_MESSAGE);
        frame.setTitle("User "+name);
        return name;
    }

    /**
     * Connects to the server then enters the processing loop.
     */
    private void run() throws IOException {

        // Make connection and initialize streams
        String serverAddress = getServerAddress();
        Socket socket = new Socket(serverAddress, 9001);
        in = new BufferedReader(new InputStreamReader(
            socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);

        // Process all messages from server, according to the protocol.

        // TODO: You may have to extend this protocol to achieve task 9 in the lab sheet
        while (true) {
            String line = in.readLine();
            if (line.startsWith("SUBMITNAME")) {
                out.println(getName());

            } else if (line.startsWith("NAMEACCEPTED")) {
                textField.setEditable(true);
            } else if (line.startsWith("MESSAGE")) {
                messageArea.append(line.substring(8) + "\n");
            }
        }
    }

    /**
     * Runs the client as an application with a closeable frame.
     */
    public static void main(String[] args) throws Exception {
        ChatClient client = new ChatClient();
        client.frame.setLocationRelativeTo(null);
        client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        client.frame.setVisible(true);
        client.run();

    }
}

0 个答案:

没有答案