Java tutorials > Input/Output (I/O) and Networking > Networking > How to implement client-server communication?
How to implement client-server communication?
Server-Side Implementation
ServerSocket
is created to listen on this port. The accept()
method blocks until a client attempts to connect. Once a connection is established, a new Socket
is created representing the connection to that client. A new thread is spawned to handle the client connection independently, preventing the server from blocking and allowing it to handle multiple clients concurrently. The handleClient()
method receives data from the client and sends a response back. It utilizes PrintWriter
for sending text data and BufferedReader
for reading text data from the client.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
int port = 12345; // Port number to listen on
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket clientSocket = serverSocket.accept(); // Blocking call - waits for a client to connect
System.out.println("Client connected: " + clientSocket.getInetAddress().getHostAddress());
// Handle client connection in a separate thread
new Thread(() -> handleClient(clientSocket)).start();
}
} catch (IOException e) {
System.err.println("Server exception: " + e.getMessage());
e.printStackTrace();
}
}
private static void handleClient(Socket clientSocket) {
try (PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Received from client: " + inputLine);
out.println("Server received: " + inputLine); // Echo back to the client
}
System.out.println("Client disconnected: " + clientSocket.getInetAddress().getHostAddress());
} catch (IOException e) {
System.err.println("Client handling exception: " + e.getMessage());
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
System.err.println("Error closing client socket: " + e.getMessage());
}
}
}
}
Client-Side Implementation
Socket
is created to establish the connection. PrintWriter
and BufferedReader
are used for sending and receiving data, respectively. The client reads input from the console (System.in
) and sends it to the server. It then waits for and displays the server's response. The client continues to send and receive messages until the user terminates the input stream (e.g., by pressing Ctrl+D).
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
String serverAddress = "localhost"; // Server address
int port = 12345; // Server port
try (Socket socket = new Socket(serverAddress, port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("Connected to server.");
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("Server response: " + in.readLine());
}
} catch (IOException e) {
System.err.println("Client exception: " + e.getMessage());
e.printStackTrace();
}
}
}
Concepts Behind the Snippet
TCP/IP: This example uses TCP/IP, a reliable, connection-oriented protocol. It ensures that data is delivered in the correct order and without errors.
Port Numbers: Port numbers are used to identify specific applications or services on a machine. Ports 0-1023 are well-known ports reserved for standard services, while ports 1024-65535 are available for user applications.
Real-Life Use Case Section
Web Browsers: Browsers act as clients, sending requests to web servers and receiving web pages in response.
Email Clients: Email clients communicate with email servers to send and receive email messages.
Database Applications: Client applications interact with database servers to store and retrieve data.
Online Games: Multiplayer games use client-server architecture to manage game state and player interactions.
Best Practices
IOException
and other exceptions to handle connection errors, data transmission failures, and other potential problems.
Resource Management: Ensure that you close sockets and streams after you are finished using them to release resources and prevent memory leaks. Using try-with-resources statements ensures that resources are closed automatically.
Thread Safety: When handling multiple client connections concurrently, ensure that your code is thread-safe to prevent race conditions and data corruption. Use appropriate synchronization mechanisms (e.g., locks) if necessary.
Security: For sensitive data, use encryption (e.g., SSL/TLS) to protect against eavesdropping and tampering.
Interview Tip
When to use them
Memory Footprint
Alternatives
HttpClient
in Java 11+) and servers (e.g., using frameworks like Spring Boot or Jakarta EE) instead of raw sockets. HTTP provides a higher-level abstraction for web communication.
Message Queues (e.g., RabbitMQ, Apache Kafka): For asynchronous communication and decoupling of services, consider using message queues. They allow you to send messages between applications without requiring direct connections.
gRPC: For building high-performance, language-agnostic microservices, consider using gRPC. It uses Protocol Buffers for efficient serialization and HTTP/2 for transport.
Pros
Flexibility: Sockets can be used for a wide range of applications and protocols beyond just web communication.
Performance: For certain use cases, sockets can offer better performance than higher-level abstractions.
Cons
Security: Implementing security features like encryption and authentication requires careful attention to detail.
Lower Level: Sockets are a lower-level abstraction, requiring more code to implement common functionalities.
FAQ
-
What is a Socket?
A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to. -
What is a ServerSocket?
AServerSocket
waits for requests to come in over the network. It performs some operation based on that request, and then possibly returns a result to the requester. -
How do I handle multiple clients concurrently?
Use threads or other concurrency mechanisms (e.g., ExecutorService, CompletableFuture) to handle each client connection in a separate thread. This prevents the server from blocking and allows it to handle multiple clients simultaneously. Ensure thread safety if shared resources are accessed by multiple threads. -
How to implement secure client-server communication?
Use SSL/TLS to encrypt the communication channel. Java provides thejavax.net.ssl
package for implementing SSL/TLS. Create aSSLSocketFactory
on the client side and aSSLServerSocketFactory
on the server side. You'll need to manage certificates and key stores properly for secure authentication.