I have assigned to create a multichat application that require to public message to all client, private message to certain client and show the user list, anyone can tell me which part should i do to implement private msg and online user list (where will show the name after client access the server, and remove the name when client close)

This is Server

public class MyChatServer {
    private static final int PORT = 3367;
    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 application main method, which just listens on a port and spawns
     * handler threads.
     */
    public static void main(String[] args) throws Exception {

        System.out.println("MyChat server is running.");
        ServerSocket listener = new ServerSocket(PORT);

        try {
            while (true) {
                new Handler(listener.accept()).start();
            }
        } finally {
            listener.close();
        }
    }

    private static class Handler extends Thread {

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

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

                //it reads one line from the buffer which is sent by client -- here name of file

                while (true) {
                    out.println("SUBMITNAME");
                    name = in.readLine();
                    if (name == null) {
                        return;
                    }
                    synchronized (names) {
                        if (!names.contains(name)) {
                            names.add(name);
                            break;
                        }
                    }
                }

                out.println("NAMEACCEPTED");
                writers.add(out);

                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 {
                if (name != null) {
                    names.remove(name);
                }
                if (out != null) {
                    writers.remove(out);
                }
                try {
                    socket.close();
                } catch (IOException e) {
                }
            }

        }      
    }

}

This is client

private String getIP() {
        return JOptionPane.showInputDialog(
                frame,
                "Please Insert IP Address",
                "MyChat Server Connection",
                JOptionPane.PLAIN_MESSAGE);

public MyChatClientPage() {
        initComponents();
        connect();
        ChatPanel.setVisible(false);
        IPPanel.setVisible(false);
        EmailPanel.setVisible(false);
        PanelMenu.setVisible(false);
        FilePanel.setVisible(false);
        btlogout.setVisible(false);
        LoginPanel.setVisible(false);
        this.pack();
        this.setLocationRelativeTo(null);
        txtmsg.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.
             */
            @Override
            public void actionPerformed(ActionEvent e) {
                out.println(txtmsg.getText());
                txtmsg.setText("");
            }
        });
    }

    private void run() throws IOException {

        // Make connection and initialize streams
        try {
            String serveraddress = getIP();
            lbltempip.setText(serveraddress);

            socket = new Socket(serveraddress, 3587);

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

            JOptionPane.showMessageDialog(null, "Connection Success!");
            LoginPanel.setVisible(true);
            this.setLocationRelativeTo(null);
            this.pack();
        } catch (UnknownHostException e) {
            JOptionPane.showMessageDialog(null, "Unknown Host! System terminated...");
            System.exit(0);
        }
        // Process all messages from server, according to the protocol.
        while (true) {
            String line = in.readLine();
            if (line.startsWith("SUBMITNAME")) {
                // out.println(PassName);
            } else if (line.startsWith("NAMEACCEPTED")) {
                txtmsg.setEditable(true);
            } else if (line.startsWith("MESSAGE")) {
                txtmsgarea.append(line.substring(8) + "\n");
            }
        }
    }

    public static void main(String args[]) throws Exception {

        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Exception e) {
            System.err.println("Look and feel not set.");
        }

        MyChatClientPage clientpage = new MyChatClientPage();
        clientpage.setVisible(true);
        clientpage.setLocationRelativeTo(null);

        clientpage.run();
        clientpage.pack();

    }

Edited 2 Years Ago by Vegito1991

Correction...

basically i able to run through localhost and ip address, and also chat with multi clients,

So if anyone can tell me which part should i do to implement private msg and online user list (where will show the name after client access the server, and remove the name when client close), i really appreaciate

My simple answer is to ignore the coding part for now and look at how this application model works. You need to be able to look at the code (and this one is very small), and then create something like a flow chart. Once you have the model (flow chart), then you will see how you can insert what you want into the flow chart. The coding part (implementation) is trivia to be honest.

Edited 2 Years Ago by Taywin

What you are asking for is a lot simpler than the code you already have, so why are you finding it difficult? (You did write that code from scratch, didn't you?) Maybe if you explain exactly why you are stuck then we will know how best to help you.

Edited 2 Years Ago by JamesCherrill

Because i still a beginner for socket programming and mostly i was refering online tutorial to solve the problem, i do understand how the message transfer after following the solution, however i still can't figure it out how to implement private message, for you might easy but for me is harder, i'm the person who read coding and do debugging to having more better understanding on how it run rather than reading on theory explanation, something like you giving me ingredients and asking me making a food without giving me the recipe

this the latest Server

public class Server {

    ArrayList clientOutputStreams;
    ArrayList<String> onlineUsers;

    public class ClientHandler implements Runnable {

        BufferedReader reader;
        Socket sock;
        PrintWriter client;

        public ClientHandler(Socket clientSocket, PrintWriter user) {
            // new inputStreamReader and then add it to a BufferedReader
            client = user;
            try {
                sock = clientSocket;
                InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
                reader = new BufferedReader(isReader);

            } // end try
            catch (Exception ex) {
                System.err.println("Error beginning StreamReader.");
            } // end catch

        } // end ClientHandler()

        public void run() {
            String message, connect = " ", disconnect = "---Disconnected---", chat = "---Message---";
            String prichat = "---Private---";
            String[] data;

            try {
                while ((message = reader.readLine()) != null) {
                    // System.err.println("Received: " + message);
                    //  outputPane.append("Received: " + message + "\n");
                    data = message.split(":");
                    for (String token : data) {
                        System.err.println(token);
                        //      outputPane.append(token + "\n");
                    }

                    if (data[2].equals(connect)) {

                        tellEveryone((data[0] + ":" + data[1] + ":" + chat));
                        userAdd(data[0]);

                    } else if (data[2].equals(disconnect)) {

                        tellEveryone((data[0] + ":has disconnected" + ":" + chat));
                        userRemove(data[0]);

                    } else if (data[2].equals(chat)) {

                        tellEveryone(message);

                    } else {
                        System.err.println("No Conditions were met.");
                    }

                } // end while
            } // end try
            catch (Exception ex) {
                System.err.println("Lost connection!");
                ex.printStackTrace();
                clientOutputStreams.remove(client);
            } // end catch
        } // end run()
    } // end class ClientHandler

    public Server() {
        Thread starter = new Thread(new Server.ServerStart());
        starter.start();
        System.err.println("MyChat Server has started.");
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Server();
            }
        });

    }

    public class ServerStart implements Runnable {

        public void run() {
            clientOutputStreams = new ArrayList();
            onlineUsers = new ArrayList();

            try {
                ServerSocket serverSock = new ServerSocket(5000);

                while (true) {
                    // set up the server writer function and then begin at the same
                    // the listener using the Runnable and Thread
                    Socket clientSock = serverSock.accept();
                    PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
                    clientOutputStreams.add(writer);

                    // use a Runnable to start a 'second main method that will run
                    // the listener
                    Thread listener = new Thread(new Server.ClientHandler(clientSock, writer));
                    listener.start();
                    System.err.println("Connection Detected!");
                } // end while
            } // end try
            catch (Exception ex) {
                System.err.println(ex);
                System.err.println("Error connection terminated.");
                System.exit(0);

            } // end catch

        } // end go()
    }

    public void userAdd(String data) {
        String message, add = ": : ", done = "Server: :Done", name = data;
        //System.err.println("Before " + name + " added.");
        onlineUsers.add(name);
        //System.err.println("After " + name + " added.");
        String[] tempList = new String[(onlineUsers.size())];
        onlineUsers.toArray(tempList);

        for (String token : tempList) {

            message = (token + add);
            tellEveryone(message);
        }
        tellEveryone(done);
    }

    public void userRemove(String data) {
        String message, add = ": : ", done = "Server: :Done", name = data;
        onlineUsers.remove(name);
        String[] tempList = new String[(onlineUsers.size())];
        onlineUsers.toArray(tempList);

        for (String token : tempList) {

            message = (token + add);
            tellEveryone(message);
        }
        tellEveryone(done);
    }

    public void tellEveryone(String message) {
        // sends message to everyone connected to server
        Iterator it = clientOutputStreams.iterator();

        while (it.hasNext()) {
            try {
                PrintWriter writer = (PrintWriter) it.next();
                writer.println(message);
                writer.flush();
            } 
            catch (Exception ex) {
                System.err.println("Error telling everyone.");

            } 
        }
    }
}

Client

public Chat() throws SQLException {
        initComponents();
        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                sendDisconnect();
                Disconnect();
                System.exit(0);
            }
        });

        txtmsg.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.
             */
            @Override

            public void actionPerformed(ActionEvent e) {
                String nothing = "";
                String userselect = List.getSelectedValue().toString();

                if ((txtmsg.getText()).equals(nothing)) {
                    txtmsg.setText("");
                    txtmsg.requestFocus();
                } else {
                    if (List.isSelectionEmpty()) {
                        JOptionPane.showMessageDialog(null, "asdasd");
                    } else if (userselect.equals("All")) {
                        try {
                            writer.println(userName + ":" + txtmsg.getText() + " :" + "---Message---");
                            writer.flush(); // flushes the buffer
                        } catch (Exception ex) {
                            chatTextArea.append("Message was not sent. \n");
                        }
                        txtmsg.setText("");
                        txtmsg.requestFocus();
                    } else if (userselect.equals(userName)) {
                        try {
                            // writer.println("[" + userName + " > Me] : " + txtmsg.getText() + ":" + "Chat");
                            //  writer.flush(); // flushes the buffer
                            chatTextArea.append("[" + userName + " > Me] : " + txtmsg.getText() + "\n");
                        } catch (Exception ex) {
                            chatTextArea.append("Message was not sent. \n");
                        }
                        txtmsg.setText("");
                        txtmsg.requestFocus();
                    } else {
                        try {
                            //  writer.println(userName + ":" + txtmsg.getText() + " :" + "---Message---");
                            writer.println(userName + " to " + userselect + " : " + txtmsg.getText() + " :" + "---Private---");
                            writer.flush(); // flushes the buffer
                        } catch (Exception ex) {
                            chatTextArea.append("Message was not sent. \n");
                        }
                        txtmsg.setText("");
                        txtmsg.requestFocus();
                    }
                    txtmsg.setText("");
                    txtmsg.requestFocus();
                }
            }
        });
    }

    public class IncomingReader implements Runnable {

        public void run() {
            String[] data;
            String stream, done = "Done", connect = " ", disconnect = "---Disconnected---", chat = "---Message---";
            try {
                while ((stream = reader.readLine()) != null) {

                    data = stream.split(":");

                    if (data[2].equals(chat)) {

                        chatTextArea.append(data[0] + ": " + data[1] + "\n");
                        chatTextArea.setCaretPosition(chatTextArea.getDocument().getLength());

                    } else if (data[2].equals(connect)) {

                        chatTextArea.removeAll();
                        userAdd(data[0]);

                    } else if (data[2].equals(disconnect)) {

                        userRemove(data[0]);

                    } else if (data[2].equals(done)) {

                        model.removeAllElements();
                        model.addElement("All");
                        List.setModel(model);
                        writeUsers();
                        userList.clear();
                    }
                }
            } catch (Exception ex) {
            }
        }
    }

    public void ListenThread() {
        Thread IncomingReader = new Thread(new IncomingReader());
        IncomingReader.start();
    }

    public void userAdd(String data) {
        userList.add(data);
    }

    public void userRemove(String data) {
        chatTextArea.append(data + " has disconnected.\n");
    }

    public void PrivateMsg(String data) {
        chatTextArea.append(data + " has disconnected.\n");
    }

    public void writeUsers() {
        String[] tempList = new String[(userList.size())];
        userList.toArray(tempList);
        for (String token : tempList) {
            model.addElement(token);
            List.setModel(model);
        }
    }

    public void sendDisconnect() {

        String bye = (userName + ": :---Disconnected---");
        try {
            writer.println(bye); // Sends server the disconnect signal.
            writer.flush(); // flushes the buffer
        } catch (Exception e) {
            chatTextArea.append("Could not send Disconnect message.\n");
        }
    }

    public void Disconnect() {

        try {
            chatTextArea.append("Disconnected.\n");
            sock.close();
        } catch (Exception ex) {
            chatTextArea.append("Failed to disconnect. \n");
        }
        isConnected = false;
        model.removeAllElements();
        model.addElement("All");
        List.setModel(model);
    }

Edited 2 Years Ago by Vegito1991

OK, the things that i want to solve is, i using txtmsg.addActionListener to chatting just by entering after text typing, without button. I have jlist in my client side, where have "All" and other User Name that only appear after they login, if i select All, then send message to all clients, which i already solved.

Now is, i want to send message to certain clients by selecting the name in Jlist with txtmsg.addActionListener.

BTW, i got another problem, when the moment i login to the frame, Jlist is not selected and if i send message, errors wil appeared, i try using isselectionempty which if Jlist not selected when sending message, will show up the error message by using JOptionPane.showMessageDialog(null, "Please select All or user name before sending message!");, unfortunately unable to solve it, any ideas?

you have code like this:

catch (Exception ex) {
}

this:

catch (Exception ex) {
chatTextArea.append("Message was not sent. \n");
}

and this:

catch (Exception ex) {
System.err.println("Error telling everyone.");
} 

I'm not surprised you're having trouble finding all the things going wrong. always make sure to log what is going wrong, it 'll help you fix it.

absolutely. especially if you need to update/improve your code. you shouldn't print it to the ui, but putting it on the command prompt or in a log is always a good idea.
it'll tell you what went wrong, and on which line of the code the exception was thrown.

i have apply to any place that is neccessary, however, i still need some guide on which part of the coding that should i focus to implement the private message? Can give me some example? and anythings that should i involved for the implementation?

what do you mean? you should focus on the code to send a private message.
what exactly do you mean? it's your code (I assume) and your analysis, so you should be the one being able to tell us that.

what i mean is what should i use, based on the online references, they are using for loop to get the username, although coding differents, like vector and array, printstream and printwriter

this is one of the example that i found, but totally different with mine

public ServerThread findUserThread(String usr){
        for(int i = 0; i < clientCount; i++){
            if(clients[i].username.equals(usr)){
                return clients[i];
            }
        }
        return null;
    }

    if(msg.type.equals("message")){
                if(msg.recipient.equals("All")){
                    Announce("message", msg.sender, msg.content);
                }
                else{
                    findUserThread(msg.recipient).send(new Message(msg.type, msg.sender, msg.content, msg.recipient));
                    clients[findClient(ID)].send(new Message(msg.type, msg.sender, msg.content, msg.recipient));
                }
            }

sorry to ask such silly questions but i still beginner level of socket programming since only learned around 15 days

In my code, i have stored the connected user in clientOutputStreams as ArrayList, below codes is where i send message to all clients at contained inside the list by the coding below

public void tellEveryone(String message) {
        // sends message to everyone connected to server
        Iterator it = clientOutputStreams.iterator();

        while (it.hasNext()) {
            try {
                PrintWriter writer = (PrintWriter) it.next();
                writer.println(message);
                writer.flush();

            } catch (Exception ex) {
                System.err.println("Error telling everyone.");
                ex.printStackTrace();
            }
        }
    }

in the client side, i send message by

writer.println(userName + ":" + txtmsg.getText() + " :" + "---Private---" + " :" + userselect);

which the message will become like
Gary: how are you : ---Message--- : userselect

userselect is part of Jlist which to select the user that i want to send the private message

while, i using this to split the data

while ((message = reader.readLine()) != null) {
                    data = message.split(":");

where become

userName = data[0]
txtmsg.getText() = data[1]
---Message--- = data[2]
userselect = data[3]

when

else if (data[2].equals("---Private---"))

then from here i want to send the private message by using iterator, but how to search the element in the arraylist by using iterator?

this are the codes that currently i working

public void tellSomeone(String data, String message) {
        // sends message to someone connected to server

        String name = data;
        Iterator it = clientOutputStreams.listIterator();

        while (it.hasNext()) {
            try {
                PrintWriter writer = (PrintWriter) it.next();
                writer.println(message);
                writer.flush();
            } catch (Exception ex) {
                System.err.println("Error telling everyone.");
                ex.printStackTrace();
            }
        }
    }

String data is represent the data in the arraylist which i pointed to the userselect, userselect = data[3], and String message is the message

So, how i use this data[3] to search the elements inside the ArrayList (clientOutputStreams) by iterator, then how to use Printwriter to send the message to that client?

i have try to use this it.next().equals(name); to replace it.next() in the Printwriter statement, but it says boolean cannot convert to printwriter

Edited 2 Years Ago by Vegito1991

i had tried this but not working

tellSomeone(data[3], message);

while (it.hasNext()) {
        try {
            if (it.next().equals(name)) {
                Object obj = it.next().equals(name);
                PrintWriter writer = (PrintWriter) obj;
                writer.println(message);
                writer.flush();
            }

        } catch (Exception ex) {
            System.err.println("Error telling everyone.");
            ex.printStackTrace();
        }
    }

Edited 2 Years Ago by Vegito1991

"but not working" is a lousy description. what is not working? don't you get the expected results? is there an exception thrown? is there a stacktrace? do you get an unexpected result? did you debug? does it even go through the loop?

i have use System.out.println(obj) to check if can display the users, and yes it is, however, i have change the coding and the message that i send still cannot display in the receiver's screen.

lets says receiver is data[0] where stored Boyz
in the Arraylist (clientOutputStreams) has Boyz and Gary

i want using Gary to send message to Boyz and the message must appeared in Boyz screen

my current codes

ArrayList clientOutputStreams;
clientOutputStreams = new ArrayList();
Socket clientSock = serverSock.accept();
PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
clientOutputStreams.add(writer);  



    public void tellSomeone(String data, String message) {

    //data represent data[0]

    String name = data;
    Iterator it = clientOutputStreams.listIterator();

    while (it.hasNext()) {
                try {
                    if (it.next().toString().equals(name)) {
                        Object obj = it.next().toString().equals(name);
                        System.out.println(obj);
                        PrintWriter writer = (PrintWriter) obj;
                        writer.println(message);
                        writer.flush();
                    }
                } catch (Exception ex) {
                    System.err.println("Error telling everyone.");
                    ex.printStackTrace();
                }
            }
    }

I not sure what is the problem but seems like if statement can't find the name

i found the error,

java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.io.PrintWriter

which caused by the obj in the Printwriter

Edited 2 Years Ago by Vegito1991

indeed, your problem is here:

Object obj = it.next().toString().equals(name);
System.out.println(obj);
PrintWriter writer = (PrintWriter) obj;

looks like you are trying to cast the wrong reference variable to a PrintWriter

or ... what exactly are you tring to print?

Edited 2 Years Ago by stultuske

yeah, i just found i should not do that, and i want to ask since my data[0] is String, is it able to search the name in ArrayList by using toString()? or in order to send private message, it always better to use index?

i really out of idea to solve this problem and today i spend whole today and can't even figure it out. Should i use string or index? how i find and get the client by using for loop? and how i send to the message to that person using printwriter....there are too much class that i donno how to use

well, I'm still not entirely clear what you're trying to do. most likely you want to contact the one with the ID of the person you're trying to reach, so the String

This article has been dead for over six months. Start a new discussion instead.