Display online users from server to all connected clients

女生的网名这么多〃 提交于 2019-12-13 17:14:35

问题


I'm building simple socket server-client application consisting of: Server project (which creates new client handler thread when socket is accepted) and a Client project (which establishing connection with the server and displaying gui with message thread open).

So far I'm able to connect using multiple clients and chat with no problems. I've set a command called !getusers that should display all connected users to the requesting client. When I do so, I'm suddenly unable to continue and chat, the client simply get stuck, I do get the connected users list though.

As for a request here is the entire client code:

import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import static java.lang.System.out;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ChatClient extends JFrame implements ActionListener {
String uname;
PrintWriter pw;
BufferedReader br;
JTextArea taMessages, taUserList;
JTextField tfInput;
JButton btnSend, btnExit;
Socket client;

public ChatClient(String uname, String servername) throws Exception {
    super("Connected as: " + uname);  // set title for frame
    this.uname = uname;
    client = new Socket(servername, 18524);
    br = new BufferedReader(new InputStreamReader(client.getInputStream()));
    pw = new PrintWriter(client.getOutputStream(), true);
    pw.println(uname);  // send name to server
    //bring up the chat interface
    buildInterface();
    new MessagesThread().start();  // create thread that listens for messages
}

public void buildInterface() {
    btnSend = new JButton("Send");
    btnExit = new JButton("Exit");
    //chat area
    taMessages = new JTextArea();
    taMessages.setRows(10);
    taMessages.setColumns(50);
    taMessages.setEditable(false);
    //online users list
    taUserList = new JTextArea();
    taUserList.setRows(10);
    taUserList.setColumns(10);
    taUserList.setEditable(false);
    //top panel (chat area and online users list
    JScrollPane chatPanel = new JScrollPane(taMessages, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    JScrollPane onlineUsersPanel = new JScrollPane(taUserList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    JPanel tp = new JPanel(new FlowLayout());
    tp.add(chatPanel);
    tp.add(onlineUsersPanel);
    add(tp, "Center");
    //user input field
    tfInput = new JTextField(50);
    //buttom panel (input field, send and exit)
    JPanel bp = new JPanel(new FlowLayout());
    bp.add(tfInput);
    bp.add(btnSend);
    bp.add(btnExit);
    add(bp, "South");
    btnSend.addActionListener(this);
    tfInput.addActionListener(this);//allow user to press Enter key in order to send message
    btnExit.addActionListener(this);
    setSize(500, 300);
    setVisible(true);
    pack();
}

@Override
public void actionPerformed(ActionEvent evt) {
    if (evt.getSource() == btnExit) {
        pw.println("!end");  // send end to server so that server know about the termination
        System.exit(0);
    } else if(tfInput.getText().contains("!getusers")){
            pw.println("!getusers");
    }else{
        // send message to server
        pw.println(tfInput.getText());
    }
}

public static void main(String args[]) {

    // take username from user
    String name = JOptionPane.showInputDialog(null, "Enter your name: ", "Username",
            JOptionPane.PLAIN_MESSAGE);
    String servername = "localhost";
    try {
        new ChatClient(name, servername);
    } catch (Exception ex) {
        out.println("Unable to connect to server.\nError: " + ex.getMessage());
    }

} // end of main

// inner class for Messages Thread
class MessagesThread extends Thread {

    @Override
    public void run() {
        String line;
        try {
            while (true) {
                line = br.readLine();
                taMessages.append(line + "\n");
                taMessages.setCaretPosition(taMessages.getDocument().getLength());//auto scroll to last message
            } // end of while
        } catch (Exception ex) {
        }
    }
    }
} //  end of client

Which then accepted and handled by the server, following is the entire server code:

public class ChatServer {

    Vector<String> users = new Vector<String>();
    Vector<HandleClient> clients = new Vector<HandleClient>();

    public void process() throws Exception {
        ServerSocket server = new ServerSocket(18524);
        out.println("Server Started...");
        while (true) {
            Socket client = server.accept();
            //add incoming client to connected clients vector.
            HandleClient c = new HandleClient(client);
            clients.add(c);
        }  // end of while
    }

    public static void main(String... args) throws Exception {
        new ChatServer().process();
    } // end of main

    public void broadcast(String user, String message) {
        // send message to all connected users
        for (HandleClient c : clients) {
            c.sendMessage(user, message);
        }
    }

    /*
     * Inner class, responsible of handling incoming clients.
     * Each connected client will set as it's own thread.
     */
    class HandleClient extends Thread {

        String name = "";//client name/username
        BufferedReader input;//get input from client
        PrintWriter output;//send output to client

        public HandleClient(Socket client) throws Exception {
            // get input and output streams
            input = new BufferedReader(new InputStreamReader(client.getInputStream()));
            output = new PrintWriter(client.getOutputStream(), true);
            // read name
            name = input.readLine();
            users.add(name); // add to users vector
            broadcast(name, " Has connected!");
            start();
        }

        public void sendMessage(String uname, String msg) {
            output.println(uname + ": " + msg);
        }

        public void getOnlineUsers() {
            for (HandleClient c : clients) {
                for (int i = 0; i < users.size(); i++) {
                    broadcast("", users.get(i));
                }
            }
        }

        public String getUserName() {
            return name;
        }

        public void run() {
            String line;
            try {
                while (true) {
                    line = input.readLine();
                    if (line.equals("!end")) {
                        //notify all for user disconnection
                        broadcast(name, " Has disconnected!");
                        clients.remove(this);
                        users.remove(name);
                        break;
                    } else if(line.equals("!getusers")){
                        getOnlineUsers();
                        break;
                    }
                    broadcast(name, line); // method  of outer class - send messages to all
                } // end of while
            } // try
            catch (Exception ex) {
                System.out.println(ex.getMessage());
            }
        } // end of run()
    } // end of inner class
} // end of Server

Should I defince a new PrintWriter object for handling the onlineUsers request? I'm sure I'm missing something here, but yet to figure out what exactly.


回答1:


Ah, I have solved the puzzle.

public void run() {
        String line;
        try {
            while (true) {
                line = input.readLine();
                if (line.equals("!end")) {
                     // Blah
                } else if(line.equals("!getusers")){
                    getOnlineUsers();
                    break;    << This breaks your read loop
                }
                broadcast(name, line); // method  of outer class - send messages to all
            } // end of while
        } // try
        catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    } // end of run()

The break statement in your run() loop terminates your reading loop, so the server is no longer "listening" to your client. I believe if you remove the break, it should be all good.



来源:https://stackoverflow.com/questions/16336123/display-online-users-from-server-to-all-connected-clients

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!