Moving from the article Hello TCP sockets

We want to make a continuous one-to-one chat between two nodes
the two nodes at the beginning would be client and server
after connection establishment they should act similar as two nodes

Server
The code in the server would be just two lines
the first line to initialize a server socket
and the second line to wait for an incoming connection from a client
once a client connects to the server, a socket returns.

ServerSocket serverSocket = new ServerSocket(3434);
Socket socket = serverSocket.accept();

Client
On the other hand the client would contain only one line, that is responsible for connection for the service running on a specific port on the server IP
once a server accepts the connection, a socket returns.

Socket socket = new Socket("127.0.0.1", 3434);

Chat Handler
at the two sides (server and client) we have a socket object that links each.
we need single handler for both to manage the conversation.
The handler should contain two fields an Input Stream to receive messages and an Output Stream to send messages

DataInputStream in;
DataOutputStream out;
.
.
    in = new DataInputStream(socket.getInputStream());
    out = new DataOutputStream(socket.getOutputStream());

Speak
to send a message to the other node, simply write a UTF message in the Output Stream

public void speak(String text)
{
    try {
        System.out.println("speak : " + text);
        frame.putMessage("I : " + text);
        out.writeUTF(text);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

Listen
to listen for a message we should use the read method in the Input Stream
a problem here is that any read method is a blocking method, so our application would hang until it receives a message. Thtat’s why we should put listening code inside a separate thread.
we could do so by extending Thread in our handler and implementing its run method.

@Override
public void run() {
    while(true)
    {
        try {
            String text = in.readUTF();
            System.out.println("listen : " + text);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

GUI
we have now a handler that can speak and listen (write and read)
we only need an interface to our chat program
we would make a Chat frame that extends JFrame and has three chat components

  • Text input (JTextField)
  • Submit button (JButton)
  • Chat history (JTextArea)

The button should call the speak method in the handler
and the listen code in the handler should put a message in the chat history


ChatFrame

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ChatFrame extends JFrame {
    
    JTextField input;
    JButton submit;
    JTextArea chatHistory;

    ChatHandler chatHandler;
    public ChatFrame(ChatHandler handler) {
        super("Messenger");
        
        this.chatHandler = handler;
        
        setLayout(new BorderLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        chatHistory = new JTextArea(20, 40);
        chatHistory.setEditable(false);
        add(chatHistory, BorderLayout.CENTER);
        
        input = new JTextField(15);
        submit = new JButton("Submit");
        
        JPanel sendPanel = new JPanel();
        sendPanel.add(input);
        sendPanel.add(submit);
        add(sendPanel, BorderLayout.SOUTH);
        
        pack();

        submit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                chatHandler.speak(input.getText());
            }
        });
    }
    
    public void putMessage(String message)
    {
        chatHistory.append("\n" + message);
    }
 
}


ChatHandler

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class ChatHandler extends Thread {
    
    DataInputStream in;
    DataOutputStream out;
    String name;
    
    ChatFrame frame;

    public ChatHandler(Socket socket) {
        try {
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        
        frame = new ChatFrame(this);
        frame.setVisible(true);
        
        start();
    }

    @Override
    public void run() {
        while(true)
        {
            try {
                String text = in.readUTF();
                System.out.println("listen : " + text);
                frame.putMessage("U : " + text);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
    
    public void listen()
    {
        try {
            String text = in.readUTF();
            System.out.println("listen : " + text);
            frame.putMessage("U : " + text);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
    public void speak(String text)
    {
        try {
            System.out.println("speak : " + text);
            frame.putMessage("I : " + text);
            out.writeUTF(text);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
}


Server

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(3434);
            
            System.out.println("Server : waiting");
            Socket socket = serverSocket.accept();
            System.out.println("Server : accept client");
            new ChatHandler(socket);
            
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}


Client

package single.chat;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 3434);
            new ChatHandler(socket);
            
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}