Create a chat app with java sockets
In this article we will implement a client/server chat app using Java sockets. This tutorial is about the backend implementation of this chat app using threads. We will explain the concepts and implemention step by step.
Basic Concepts
Server :
To communicate with the client, the server uses two type of sockets
ServerSocket : this class is used by the server to declare a ServerSocket object which the server needs to listen to connection requests from the clients
Socket : this class is used by the server to declare a Socket object, which the server uses to send and recieve data from the client
Client :
To communicate with the server, the client uses one single socket which’s an object from Socket class, to send and recieve data from server
=> the instantiating of Socket class in server and client is different even though it is the same class but it differs from client to the server
Implementation
Using IntelliJ IDEA , I created a project named “ chat “ then under the src folder I created two Java classes : Server.java and Client.java
Now let’s implement Server.java class :
1- Server.java
To begin with, we declare 5 objects:
- final ServerSocket serversocket : this line means we declared an object called “ serversocket” which is an object of the class ServerSocket. It is declared “ final” which means it is a constant
- final Socket clientSocket : this line means we declared an object called “ clientsocket” which is an object of the class Socket. It is declared “ final” which means it is a constant
- final BufferedReader in : this line means we declared an object called “ in” which is an object of the class BufferedReader. It is used to read data from the clientSocket object
- final PrintWriter out : this line means we declared an object called “ out ” which is an object of the class PrintWriter. It is used to write data into the clientsocket object
=> In all above code, we just declared the objects , we still didn’t instanciate them.
- final Scanner sc = new Scanner(System.in) : this line of code means we created an object from the class Scanner called “ sc” to be able to read data from the user’s keybord
Now let’s instanciate the serversocket object:
As you see, the constructor of ServerSocket class must take a port number that the server will use to listen to client’s requests , also the instantiating should be in try/catch
As previously said , the serversocket is used by the server to listen to connection requests from client, it uses the method accept() to wait for a request from the client , once it recieves one it accept it and create an instance of the Socket class which in our case will be the “clientsocket” object.
To instantiate “ out “, we use the constructor of PrintWriter class, this constructor takes one parameter which is an output stream for the socket , notice that the socket used here is clientSocket , because it is responsible for sending data to the client.
Now “ out “ is ready to write data into “ clientsocket” !
In this part we instantiate the “ in “ object that we will use to read from clientSocket. The constructor here will call another constructor as a parameter
new InputStreamReader( clientSocket.getInputStream()) : creates a stream reader for the socket. However this stream reader only reads data as Bytes , therefore it must be passed to BufferedReader to be converted into characters.
Now that all objects we will use are created, we will start implementing two threads :
Sender thread : it contains the code the server will use to send messages to client
Recieve thread : it contains the code the server will use to recieve messages from client
Sender thread
Now in this part, we will read data from user and we send this data to the client.
The class Thread in Java has its own default run() method which should contains the code that the thread will execute. However it can’t be executed, unless you call the method start() on that thread . Also , Since in every different thread we have a different code to implement , we use @Override annotation .
Recieve thread
In this part we implement the recieve thread.
We read data that is sent from the client using the “ in” object associated to the clientSocket using the method readLine().
This method reads line by line the message sent by the client, if this method returns null that means that the client is not connected anymore. It doesn’t mean that the client didn’t send anything because the client can be connected to the server and still doesn’t send anything.
When the client is not connected to the server anymore we should close all sockets and streams we used using the method close(). Also, we put all the code inside a try/catch so we can print any error related to reading data or closing sockets and streams.
The server is now ready for communication !
Here’s full code
Now let’s implement Client.java class :
2- Client.java
As you see most of the code in the client side is the same as the server, so I will only explain the selected line which is different in the client.
When we declare the client’s socket which he will use to communicate with the server , the constructor of the Socket class takes two parameters :
host : which is the IP address of the server , in our case the server and client are both implemented on the same machine so we use the address localhost which is : 127.0.0.1
port : a port number which is the port number defined by the server in the Server.java
Now, the client also has two threads one for sending data and the other for recieving data, they are implemented the same way as the server’s threads
Now the client is ready for communication
here’s the full code :
3- Execution
let’s see how this works
First run the Server.java class then Client.java class
You can download project from my github repository using the link :