0

I've been working on building a chat server to learn about threading and using sockets. I used head first java as a guide (and I'm still confused about a couple of things, which is why I have this question probably :D) and the code below is what I have.

If you read my code, you'll see that I have clients connect to the server by clicking on a "connect" button. When they do that, a new jframe pops up that asks for their preferred name for the chat session. When they input that, it's saved in a String in the client code. My question is, how do I get this name over to the server, and make it so that every time the client sends a message, their name is displayed before their message?

Thank you for the help!!!

(ALSO, if anyone knows a good link that can explain sockets and how socket/client interaction occurs through threads, that would be great!)

server code:

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;


public class GameServerOne {
    ArrayList clientOutputStreams;
    String clientName;
    private class ClientThreadHandler implements Runnable {
        BufferedReader clientIncomingReader;
        Socket socket1;
        public ClientThreadHandler(Socket clientSocket2) {
            try {
                socket1 = clientSocket2;
                InputStreamReader clientInputReader = new InputStreamReader(socket1.getInputStream());
                clientIncomingReader = new BufferedReader(clientInputReader);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public void run() {
            String message;
            try {
                while ((message = clientIncomingReader.readLine()) != null) {
                    tellEveryone(message);
                }
            } catch (Exception e) { 
                e.printStackTrace();
            }
        }
    }
    public void tellEveryone(String message) {
        Iterator it = clientOutputStreams.iterator();
        while(it.hasNext()) {
            try {
                PrintWriter writer = (PrintWriter) it.next();
                writer.println(message);
                writer.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void setUpServer() {
        clientOutputStreams = new ArrayList();
        try {
            ServerSocket gameSocket = new ServerSocket(5151);
            //System.out.println("Server Connected");

            while (true) {
                Socket clientSocket = gameSocket.accept();
                PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
                writer.println("User connected");
                writer.flush();
                clientOutputStreams.add(writer);
                Thread t = new Thread(new ClientThreadHandler(clientSocket));
                t.start();


            }

        } catch (Exception ex) {
                ex.printStackTrace();
        }
    }
    public static void main(String[] args) {
        new GameServerOne().setUpServer();
    }


}

Client code:

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class GameClientOne {
    Socket gameSocket;
    JFrame inputNameFrame;
    JFrame clientFrame;
    JTextArea chatArea;
    JTextField messageInput;
    BufferedReader gameChatReader;
    PrintWriter gameChatWriter;
    JTextField nameField;
    boolean sessionNamePicked = false;
    String userSessionName;
    BufferedReader gameBufferedReader;



    public GameClientOne () {
        setUpGUI();
    }

    public void setUpGUI() {
        clientFrame = new JFrame("Game Window");
        JPanel mainPanel = new JPanel(new BorderLayout());
        JPanel southPanel = new JPanel(new BorderLayout());
        JPanel centerPanel = new JPanel(new BorderLayout());
        chatArea = new JTextArea();
        chatArea.setWrapStyleWord(true);
        chatArea.setLineWrap(true);
        chatArea.setEditable(false);
        JScrollPane chatScroller = new JScrollPane(chatArea);
        messageInput = new JTextField();
        messageInput.addKeyListener(new MessageInputFieldListener());
        JButton sendButton = new JButton("Send");
        sendButton.addActionListener(new SendButtonListener());
        JPanel westPanel = new JPanel(/*new GridLayout(20, 1)*/);
        JPanel eastPanel = new JPanel();
        JButton connectButton = new JButton("Connect");
        connectButton.addActionListener(new ConnectButtonListener());
        connectButton.setPreferredSize(new Dimension(100, 28));
        JPanel northPanel = new JPanel(new FlowLayout());
        JLabel northTitleLabel = new JLabel("Game Screen");
        westPanel.add(connectButton);
        chatScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) ; 
        chatScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);



        northPanel.add(northTitleLabel);
        centerPanel.add(BorderLayout.CENTER, chatScroller);
        southPanel.add(BorderLayout.CENTER, messageInput);
        southPanel.add(BorderLayout.EAST, sendButton);
        mainPanel.add(BorderLayout.SOUTH, southPanel);
        mainPanel.add(BorderLayout.CENTER, centerPanel);
        mainPanel.add(BorderLayout.WEST, westPanel);
        mainPanel.add(BorderLayout.EAST, eastPanel);
        mainPanel.add(BorderLayout.NORTH, northPanel);

        clientFrame.add(mainPanel);
        clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        clientFrame.setSize(450, 600);
        clientFrame.setVisible(true);
        messageInput.requestFocusInWindow();

    }
    public void setUpInputNameFrame() {
        inputNameFrame = new JFrame("Insert Name");
        JPanel mainPanel = new JPanel(new BorderLayout());
        nameField = new JTextField();
        nameField.addKeyListener(new NameFieldListener());
        JButton submitButton = new JButton("Submit");
        submitButton.addActionListener(new SubmitButtonListener());
        JLabel inputNameLabel = new JLabel("Please pick a name for the chat session");
        JPanel northPanel = new JPanel(new FlowLayout());
        JPanel southPanel = new JPanel(new BorderLayout());
        northPanel.add(inputNameLabel);
        southPanel.add(BorderLayout.CENTER, nameField);
        southPanel.add(BorderLayout.EAST, submitButton);
        mainPanel.add(BorderLayout.NORTH, northPanel);
        mainPanel.add(BorderLayout.SOUTH, southPanel);
        inputNameFrame.add(mainPanel);
        inputNameFrame.setSize(300, 150);
        inputNameFrame.setVisible(true);
        nameField.requestFocusInWindow();
    }

    public void connectToGameServer() {
            try {

                gameSocket = new Socket("127.0.0.1", 5151);
                InputStreamReader gameSocketReader = new InputStreamReader(gameSocket.getInputStream());
                gameBufferedReader = new BufferedReader(gameSocketReader);
                gameChatWriter = new PrintWriter(gameSocket.getOutputStream());
                chatArea.append("Connected with name: " + userSessionName + "\n");
                Thread incomingTextThread = new Thread(new IncomingTextReader());
                incomingTextThread.start();
                //System.out.println("Connected to Game");
            } catch (Exception e) {
                System.out.println("Could not connect to game...");
                e.printStackTrace();
            }

    }

    //ALL LISTENER CLASSES BELOW HERE
    //main chat page listeners
    private class ConnectButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if (!sessionNamePicked) {
                setUpInputNameFrame();
            } else {
                chatArea.append("You already connected!\n");
            }


        }
    }
    private class SendButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if (!sessionNamePicked)  {
                chatArea.append("Please connect first\n");
                messageInput.setText("");
                messageInput.requestFocusInWindow();
            } else {
                try {
                    gameChatWriter.println(messageInput.getText());
                    gameChatWriter.flush();
                } catch (Exception ex2) {
                    ex2.printStackTrace();
                }
                //chatArea.append(userSessionName + ": " + messageInput.getText() + "\n");
                messageInput.setText("");
                messageInput.requestFocusInWindow();
            }
        }
    }
    private class MessageInputFieldListener implements KeyListener {
        public void keyPressed(KeyEvent e) {

        }
        public void keyTyped(KeyEvent e) {

        }
        public void keyReleased(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                if (!sessionNamePicked)  {
                    chatArea.append("Please connect first\n");
                    messageInput.setText("");
                } else {
                    try {
                        gameChatWriter.println(messageInput.getText());
                        gameChatWriter.flush();
                    } catch (Exception ex2) {
                        ex2.printStackTrace();
                    }
                    //chatArea.append(userSessionName + ": " + messageInput.getText() + "\n");
                    messageInput.setText("");
                }
            }
        }
    }

    //pick chat session name listeners: nameField/submitButton
    private class NameFieldListener implements KeyListener {
        public void keyPressed(KeyEvent e) {

        }
        public void keyTyped(KeyEvent e) {

        }
        public void keyReleased(KeyEvent e) {
                if (!nameField.getText().isEmpty() && e.getKeyCode() == KeyEvent.VK_ENTER) {
                    userSessionName = nameField.getText();
                    sessionNamePicked = true;
                    connectToGameServer();
                    inputNameFrame.dispose();
                    messageInput.requestFocusInWindow();
                }

        }
    }
    private class SubmitButtonListener implements ActionListener {
        public void actionPerformed (ActionEvent e) {
            if (!nameField.getText().isEmpty()) {
                userSessionName = nameField.getText();
                sessionNamePicked = true;
                connectToGameServer();
                inputNameFrame.dispose();
                messageInput.requestFocusInWindow();
            }
        }
    }
    //Runnable implementation for threads
    private class IncomingTextReader implements Runnable {
        public void run() {
            String incomingMessage;
            try {
                while ((incomingMessage = gameBufferedReader.readLine()) != null) {
                    chatArea.append(incomingMessage + "\n");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {
        GameClientOne gameClient = new GameClientOne();
    }


}
Abdul Ahmad
  • 9,673
  • 16
  • 64
  • 127
  • See the examples [here](http://stackoverflow.com/a/3245805/230513) and [here](http://stackoverflow.com/a/14617650/230513). – trashgod Jan 21 '14 at 01:21

1 Answers1

1

If you want to send more than just a message as you are now, you are going to need a protocol to decide what to do with the string you receive, instead of just sending it to all the other clients.

For example, on the client side to send the client's name you might write NAME:(client's name), and then on the server you would split the string at the : and check if the first part is NAME, and if so set the clients name to the rest of the string. You should think about what other types of data you might want to send aswell and design a protocol that works for it.

Here's an example of how to do the above:

On the client you could add the line gameChatWriter.write("NAME:"+name) (create name first of course) imediatly after the connection is made. Then on the server, instead of calling tellEveryone(message) when the message is recieved create a method called processInput and call it, which might look like this:

private void processInput(String message){
    String[] commands=message.split(':');
    if(commands[0].equals("NAME")){
        clientName=commands[1];
    }
    else{
        tellEveryone(message);
    }
}

Right now you only have one String clientName and you will obviously need more for the other clients you want to talk to so I would recommend making the thread handler into a seperate class which you would instantiate for each client and could hold things like that.

After you get this to work you could also create a seperate method to write other things that you want to send to either the client or server and a method to process input on the client side as well. Hope this helps.

Alex - GlassEditor.com
  • 14,957
  • 5
  • 49
  • 49
  • if you don't mind me bothering you for a minute, can you give me a quick example of how to do this protocol. I'm a newb and need some assistance – Abdul Ahmad Jan 21 '14 at 01:37