Prerequisites: Socket Programming in Java
Multithreaded Server: A server having more than one thread is known as Multithreaded Server. When a client sends the request, a thread is generated through which a user can communicate with the server. We need to generate multiple threads to accept multiple requests from multiple clients at the same time.

Advantages of Multithreaded Server:
- Quick and Efficient: Multithreaded server could respond efficiently and quickly to the increasing client queries quickly.
- Waiting time for users decreases: In a single-threaded server, other users had to wait until the running process gets completed but in multithreaded servers, all users can get a response at a single time so no user has to wait for other processes to finish.
- Threads are independent of each other: There is no relation between any two threads. When a client is connected a new thread is generated every time.
- The issue in one thread does not affect other threads: If any error occurs in any of the threads then no other thread is disturbed, all other processes keep running normally. In a single-threaded server, every other client had to wait if any problem occurs in the thread.
Disadvantages of Multithreaded Server:
- Complicated Code: It is difficult to write the code of the multithreaded server. These programs can not be created easily
- Debugging is difficult: Analyzing the main reason and origin of the error is difficult.
Quick Overview
We create two java files, Client.java and Server.java. Client file contains only one class Client (for creating a client). Server file has two classes, Server(creates a server) and ClientHandler(handles clients using multithreading).

Client-Side Program: A client can communicate with a server using this code. This involves
- Establish a Socket Connection
- Communication
Java
import java.io.*;
import java.net.*;
import java.util.*;
class Client {
public static void main(String[] args)
{
try (Socket socket = new Socket( "localhost" , 1234 )) {
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true );
BufferedReader in
= new BufferedReader( new InputStreamReader(
socket.getInputStream()));
Scanner sc = new Scanner(System.in);
String line = null ;
while (! "exit" .equalsIgnoreCase(line)) {
line = sc.nextLine();
out.println(line);
out.flush();
System.out.println( "Server replied "
+ in.readLine());
}
sc.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
|
Server-Side Program: When a new client is connected, and he sends the message to the server.
1. Server class: The steps involved on the server side are similar to the article Socket Programming in Java with a slight change to create the thread object after obtaining the streams and port number.
- Establishing the Connection: Server socket object is initialized and inside a while loop a socket object continuously accepts an incoming connection.
- Obtaining the Streams: The inputstream object and outputstream object is extracted from the current requests’ socket object.
- Creating a handler object: After obtaining the streams and port number, a new clientHandler object (the above class) is created with these parameters.
- Invoking the start() method: The start() method is invoked on this newly created thread object.
2. ClientHandler class: As we will be using separate threads for each request, let’s understand the working and implementation of the ClientHandler class implementing Runnable. An object of this class acts as a Runnable target for a new thread.
- First, this class implements Runnable interface so that it can be passed as a Runnable target while creating a new Thread.
- Secondly, the constructor of this class takes a parameter, which can uniquely identify any incoming request, i.e. a Socket.
- Inside the run() method of this class, it reads the client’s message and replies.
Java
import java.io.*;
import java.net.*;
class Server {
public static void main(String[] args)
{
ServerSocket server = null ;
try {
server = new ServerSocket( 1234 );
server.setReuseAddress( true );
while ( true ) {
Socket client = server.accept();
System.out.println( "New client connected"
+ client.getInetAddress()
.getHostAddress());
ClientHandler clientSock
= new ClientHandler(client);
new Thread(clientSock).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (server != null ) {
try {
server.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket socket)
{
this .clientSocket = socket;
}
public void run()
{
PrintWriter out = null ;
BufferedReader in = null ;
try {
out = new PrintWriter(
clientSocket.getOutputStream(), true );
in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
String line;
while ((line = in.readLine()) != null ) {
System.out.printf(
" Sent from the client: %s\n" ,
line);
out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (out != null ) {
out.close();
}
if (in != null ) {
in.close();
clientSocket.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
|
Steps:
- Compile both Client and Server programs.
- Run the server first and then the Client.
Output

Feeling lost in the vast world of Backend Development? It's time for a change! Join our
Java Backend Development - Live Course and embark on an exciting journey to master backend development efficiently and on schedule.
What We Offer:
- Comprehensive Course
- Expert Guidance for Efficient Learning
- Hands-on Experience with Real-world Projects
- Proven Track Record with 100,000+ Successful Geeks
Last Updated :
09 Nov, 2020
Like Article
Save Article