Of course! Let's dive deep into ServerSocket in Java. It's a fundamental class for creating network servers that listen for incoming client connections.

What is a ServerSocket?
Think of a ServerSocket as a door or a receptionist for your server application.
- It Listens: It binds to a specific network port on your machine and waits (listens) for a client to try and connect.
- It Accepts: When a client attempts to connect, the
accept()method "picks up the phone" or "opens the door," creating a newSocketthat represents a direct, two-way communication channel with that specific client. - It's the Entry Point: You create one
ServerSocketfor your entire server. It's not the communication channel itself; it's the factory for communication channels (Socketobjects).
Key Concepts and Workflow
Here is the typical lifecycle of a server using ServerSocket:
- Create a
ServerSocket: Specify the port number you want to listen on. - Call
accept(): This is a blocking method. The program will pause here and wait indefinitely until a client connects. When a client connects,accept()returns a newSocketobject for that client. - Communicate: Use the
Socketobject'sInputStreamandOutputStream(orgetInputStream()andgetOutputStream()) to send and receive data with the client. - Close: After you're done communicating with the client, close the client's
Socket. TheServerSocketcan then go back to listening for new clients on theaccept()call.
A Simple Example: Echo Server
An "Echo Server" is a classic example. It listens for a connection, receives a message from the client, and sends the exact same message back.
The Server Code (EchoServer.java)
import java.io.*;
import java.net.*;
public class EchoServer {
public static void main(String[] args) {
// The port number we will listen on
int port = 6789;
// Use a try-with-resources block to automatically close the ServerSocket
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
// The accept() method blocks until a client connects
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress());
// Use try-with-resources for the streams to ensure they are closed
try (InputStream input = clientSocket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = clientSocket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true)) { // autoFlush=true
String text;
// Read lines from the client until "exit" is sent
while ((text = reader.readLine()) != null) {
System.out.println("Received from client: " + text);
if ("exit".equalsIgnoreCase(text)) {
System.out.println("Client requested to close the connection.");
break;
}
// Echo the received message back to the client
writer.println("Server: " + text);
}
} catch (IOException e) {
System.err.println("Error handling client communication: " + e.getMessage());
} finally {
// Ensure the client socket is closed
clientSocket.close();
System.out.println("Client disconnected.");
}
} catch (IOException e) {
System.err.println("Server exception: " + e.getMessage());
e.printStackTrace();
}
}
}
How to Run It:
- Save the code as
EchoServer.java. - Compile it:
javac EchoServer.java - Run it:
java EchoServer - You will see the output:
Server is listening on port 6789. The program will now wait.
A Simple Client to Test the Server
To test our server, we need a client. Here's a simple one that connects and sends messages.

The Client Code (EchoClient.java)
import java.io.*;
import java.net.*;
public class EchoClient {
public static void main(String[] args) {
String hostname = "localhost"; // or "127.0.0.1"
int port = 6789;
try (Socket socket = new Socket(hostname, port);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("Connected to the echo server.");
System.out.println("Type a message and press Enter. Type 'exit' to quit.");
String text;
// Read from the console and send to the server
while (true) {
System.out.print("You: ");
text = consoleReader.readLine();
if (text == null || "exit".equalsIgnoreCase(text)) {
break;
}
writer.println(text);
// Read the echoed message from the server
String serverResponse = reader.readLine();
if (serverResponse != null) {
System.out.println("Server: " + serverResponse);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostname);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostname + ". Is the server running?");
}
}
}
How to Run the Test:
- Open two terminal/command prompt windows.
- In the first window, run the server:
java EchoServer - In the second window, compile and run the client:
javac EchoClient.javathenjava EchoClient - In the client window, you can type messages and see them echoed back by the server.
Important Methods of ServerSocket
| Method | Description |
|---|---|
ServerSocket(int port) |
Constructor that creates a server socket, bound to the specified port. |
Socket accept() |
Listens for a connection to be made to this socket and accepts it. This is a blocking call. |
close() |
Closes the server socket. If a thread is blocked in accept(), it will throw a SocketException. |
getInetAddress() |
Returns the local address to which this socket is bound. |
getLocalPort() |
Returns the port number on which this socket is listening. |
isBound() |
Returns the binding state of the socket. |
isClosed() |
Returns the closed state of the socket. |
Advanced Topics and Best Practices
Handling Multiple Clients (Threading)
The simple EchoServer can only handle one client at a time because accept() is blocking and the communication loop runs in the main thread. Real-world servers need to handle many clients simultaneously.
The solution is multithreading:
- The main thread's only job is to call
serverSocket.accept()in a loop. - When
accept()returns a newSocket, a new thread is created to handle all communication with that client. - The main thread immediately goes back to
accept()to wait for the next client.
Here's a modified EchoServer that uses a thread pool:
import java.io.*;
import java.net.*;
public class MultiThreadedEchoServer {
public static void main(String[] args) {
int port = 6789;
// Use a fixed-size thread pool to handle client connections
int maxThreads = 10;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("New client connected: " + clientSocket.getInetAddress().getHostAddress());
// Create a new thread for each client
ClientHandler clientHandler = new ClientHandler(clientSocket);
new Thread(clientHandler).start();
}
} catch (IOException e) {
System.err.println("Server exception: " + e.getMessage());
}
}
}
// A separate class to handle the client's communication
class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try (InputStream input = clientSocket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = clientSocket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true)) {
String text;
while ((text = reader.readLine()) != null) {
System.out.println("Received from " + clientSocket.getInetAddress() + ": " + text);
writer.println("Server: " + text);
}
} catch (IOException e) {
System.err.println("Error handling client: " + e.getMessage());
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Client disconnected.");
}
}
}
Setting a Timeout
The accept() method can block forever. You can set a timeout so that if no client connects within a specified time, it throws an SocketTimeoutException, allowing your code to do other things (like check a shutdown flag).
ServerSocket serverSocket = new ServerSocket(6789);
serverSocket.setSoTimeout(5000); // Wait for 5 seconds
System.out.println("Waiting for a client (5 second timeout)...");
try {
Socket socket = serverSocket.accept();
// ... handle client
} catch (SocketTimeoutException e) {
System.out.println("No client connected within 5 seconds.");
}
Reusing an Address (SO_REUSEADDR)
If your server crashes and you restart it quickly, you might get a BindException (Address already in use). This is because the old socket is in a TIME_WAIT state. You can tell the OS to reuse the address.
ServerSocket serverSocket = new ServerSocket(); serverSocket.setReuseAddress(true); // Enable SO_REUSEADDR serverSocket.bind(new InetSocketAddress(6789));
