Java Socket: Create a Client/Server Chat Application

In this tutorial, you'll learn how to create a java chat application between two machines using sockets. Before starting the programming part, you need to configure your network to make these two machines interact on the local network of your home for example. We're going to implement what we've seen in theory: the well-known Client/Server model.

By the end of this tutorial, you'll know how sockets are able to exchange messages.

Server

The javaserver> initializes the connection, listens on a port, and waits for incoming connections to accept. For example, the port number is 5000, the client sends a request to the server with this port number 5000. The server accepts the request and transmits its information (IP address) to the client. Now the connection is established and a message exchange can take place.

Java provides a package java.net that handles everything networking, you only need two classes:

  • java.net.ServerSocket: This class accepts connections from clients.
  • java.net.Socket: This class connects to the remote machine.
You also need a tool to enter, send and receive the stream:
  • Scan: Read keyboard inputs.
  • BufferedReader: Read text received from the sender.
  • PrintWriter: send the typed text.
ServerSocket socketserver; 
Socket socketofthe server;
final BufferedReader in;
final PrintWriter out;
final Scanner sc=new Scanner(System.in);
try {
socketserver = new ServerSocket(5000);
serversocket = socketserver.accept();
out = new PrintWriter(serversocket.getOutputStream());
in = new BufferedReader (new InputStreamReader (serversocket.getInputStream()));
String s;
s = sc.next();
out.println(s);
out.flush();
String message_client;
message_client = in.readLine();
System.out.println("Client: "+message_client);
}
catch (IOException e) {
e.printStackTrace();
}
After the server socket is created, which has port number 5000, the server waits for incoming connections, and as soon as one is detected, it accepts it. The two variables that handle the read and write flow in and out are initialized to be linked directly to the send and receive stream.
The variable s  stores text typed with the next(), and then it is sent with the println(s).
The flush() is important because it flushes the write buffer to the output otherwise a null will be received by the other machine.
The variable message_client stores the message   receipt that is displayed with println().

The limitation of this code is that it is able to send and receive a message only once. You'll have an idea in mind: add a loop while(true). This is true, but if, for example, the server sends a message to the client, the client cannot retrieve the message until it sends it too. The optimal solution is to create two threads: one for sending and the other for receiving. Both of these processes allow sending and receiving to happen simultaneously.

import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/*
* www.codeurjava.com
*/
public class Server {

public static void main(String[] test) {

final ServerSocket serverSocket;
final Socket clientSocket;
final BufferedReader in;
final PrintWriter out;
Scanner sc=new Scanner(System.in);

try {
serverSocket = new ServerSocket(5000);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader (new InputStreamReader (clientSocket.getInputStream()));
Thread send= new Thread(new Runnable() {
String msg;
@Override
public void run() {
while(true){
msg = sc.nextLine();
out.println(msg);
out.flush();
}
}
});
send.start();

Thread receive= new Thread(new Runnable() {
String msg;
@Override
public void run() {
try {
msg = in.readLine();
//as long as the client is connected
while(msg!=null){
System.out.println("Client: "+msg);
msg = in.readLine();
}
//exit from the loop if the client has deconected
System.out.println("Client deconected");
//close stream and session socket
out.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
receive.start();
}catch (IOException e) {
e.printStackTrace();
}
}
}

The separation of the two processes is clear, the Server and the Client can exchange data at any time and infinitely. The while loop of playback tests whether the connection is still established. Remember to close your read and write streams as well as the connection after exiting the loop with the close().

Client

Client only needs the Socket to establish the server connection, on constructor takes the server's IP address and port number as input. The rest of the code is the same as that of the server.

import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/*
* www.codeurjava.com
*/
public class Client {

public static void main(String[] args) {

final Socket clientSocket;
final BufferedReader in;
final PrintWriter out;
final Scanner sc = new Scanner(System.in);//to read from keyboard

try {
/*
* server information ( port and IP address or hostname
* 127.0.0.1 is the local address of the machine
*/
clientSocket = new Socket("127.0.0.1", 5000);

//stream to send
out = new PrintWriter(clientSocket.getOutputStream());
//stream to receive
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

Thread send = new Thread(new Runnable() {
String msg;
@Override
public void run() {
while(true){
msg = sc.nextLine();
out.println(msg);
out.flush();
}
}
});
send.start();

Receive Thread = new Thread(new Runnable() {
String msg;
@Override
public void run() {
try {
msg = in.readLine();
while(msg!=null){
System.out.println("Server: "+msg);
msg = in.readLine();
}
System.out.println("Deconected server");
out.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
receive.start();

} catch (IOException e) {
e.printStackTrace();
}
}
}
Execution:

Java tcp socket server
Server window
Client socket tcp java
Client window
Note: If you are working on the same machine, you must run Eclipse twice, one for the server and the other for the client. Watch the following YouTube video:
https://www.youtube.com/watch?v=d-eD6EDa3io


References:
Network in Java - Manipulating IP Addresses
How to Retrieve the Name and Local IP Address of the Server/Client
Openclassrooms: Introduction to sockets
Java doc: Class Socket