Networking in Java
1. Java Networking Overview
Java's java.net package provides
classes for network communication. The two primary transport
protocols are TCP and UDP:
| Feature | TCP | UDP |
|---|---|---|
| Connection | Connection-oriented (handshake required) | Connectionless |
| Reliability | Guaranteed delivery, ordered packets | No guarantee; packets may be lost or reordered |
| Speed | Slower (overhead for reliability) | Faster (minimal overhead) |
| Use cases | HTTP, FTP, email, database queries | DNS, video streaming, online gaming |
| Java class |
Socket /
ServerSocket
|
DatagramSocket /
DatagramPacket
|
Key classes in java.net:
-
InetAddress— represents an IP address. Socket— TCP client endpoint.-
ServerSocket— TCP server endpoint; listens for connections. -
DatagramSocket— UDP socket (client and server). -
DatagramPacket— UDP data container. -
URL— represents a Uniform Resource Locator. -
HttpURLConnection— makes HTTP requests.
2. InetAddress
InetAddress resolves hostnames to IP
addresses and vice versa. It supports both IPv4 and IPv6.
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// Resolve a hostname to IP
InetAddress google = InetAddress.getByName("www.google.com");
System.out.println("Host name: " + google.getHostName());
System.out.println("Host address: " + google.getHostAddress());
System.out.println("Is reachable: " + google.isReachable(3000)); // 3s timeout - requires try/catch
// Get all IP addresses for a hostname (load-balanced services)
InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
System.out.println("\nAll IPs for www.google.com:");
for (InetAddress addr : addresses) {
System.out.println(" " + addr.getHostAddress());
}
// Get local machine information
InetAddress localhost = InetAddress.getLocalHost();
System.out.println("\nLocal host name: " + localhost.getHostName());
System.out.println("Local IP: " + localhost.getHostAddress());
// Get loopback address
InetAddress loopback = InetAddress.getLoopbackAddress();
System.out.println("Loopback: " + loopback.getHostAddress()); // 127.0.0.1
// Create from raw IP bytes
byte[] ipBytes = {(byte)192, (byte)168, 1, 1};
InetAddress custom = InetAddress.getByAddress(ipBytes);
System.out.println("Custom IP: " + custom.getHostAddress()); // 192.168.1.1
}
}
Host address: 142.250.80.4
Local host name: MyPC
Local IP: 192.168.1.5
Loopback: 127.0.0.1
Custom IP: 192.168.1.1
3. Socket Programming — TCP
TCP (Transmission Control Protocol) is connection-oriented. Before data flows, a three-way handshake establishes a reliable, bidirectional connection between client and server. Java models this with two classes:
-
Server side:
ServerSocketbinds to a port and waits viaaccept(). -
Client side:
Socketconnects to the server's host and port.
Once connected, both ends communicate through
InputStream and
OutputStream obtained from the socket
— just like reading and writing a file.
Port numbers: Well-known ports are 0–1023 (HTTP=80, HTTPS=443). Use ports 1024–65535 for your own servers. Both server and client must agree on the same port number.
4. ServerSocket
The server binds to a port, accepts incoming connections in a loop, and typically spawns a new thread per client to handle multiple clients concurrently.
import java.net.*;
import java.io.*;
public class EchoServer {
private static final int PORT = 9090;
public static void main(String[] args) throws IOException {
System.out.println("Server starting on port " + PORT + "...");
// Bind to port; backlog of 5 queued connections
try (ServerSocket serverSocket = new ServerSocket(PORT, 5)) {
System.out.println("Server listening. Waiting for client...");
while (true) { // keep accepting connections
Socket clientSocket = serverSocket.accept(); // BLOCKS until a client connects
System.out.println("Client connected: "
+ clientSocket.getInetAddress().getHostAddress());
// Handle each client in a separate thread
new Thread(() -> handleClient(clientSocket)).start();
}
}
}
private static void handleClient(Socket socket) {
try (socket;
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true)) { // autoFlush=true
String line;
while ((line = in.readLine()) != null) {
System.out.println("Received: " + line);
out.println("ECHO: " + line); // echo back to client
if ("bye".equalsIgnoreCase(line)) break;
}
} catch (IOException e) {
System.err.println("Client error: " + e.getMessage());
}
System.out.println("Client disconnected.");
}
}
5. Socket (Client)
The client creates a Socket with the
server's hostname and port. This triggers the TCP handshake. The
client then communicates through streams.
import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) throws IOException {
String host = "localhost";
int port = 9090;
System.out.println("Connecting to " + host + ":" + port);
try (Socket socket = new Socket(host, port);
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in))) {
System.out.println("Connected! Type messages (type 'bye' to quit):");
String userInput;
while ((userInput = keyboard.readLine()) != null) {
out.println(userInput); // send to server
String response = in.readLine(); // read server response
System.out.println("Server: " + response);
if ("bye".equalsIgnoreCase(userInput)) break;
}
}
System.out.println("Connection closed.");
}
}
Connected! Type messages (type 'bye' to quit):
> Hello Server
Server: ECHO: Hello Server
> bye
Server: ECHO: bye
Connection closed.
6. Complete TCP Client-Server Example
Here is a self-contained example showing both server and client. Run the server first in one terminal, then the client in another.
Server — TimeServer.java
import java.net.*;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class TimeServer {
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(8080)) {
System.out.println("TimeServer running on port 8080...");
while (true) {
try (Socket client = server.accept();
PrintWriter out = new PrintWriter(
client.getOutputStream(), true)) {
String time = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
out.println("Current server time: " + time);
System.out.println("Served time to: "
+ client.getInetAddress().getHostAddress());
}
}
}
}
}
Client — TimeClient.java
import java.net.*;
import java.io.*;
public class TimeClient {
public static void main(String[] args) throws IOException {
try (Socket socket = new Socket("localhost", 8080);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
System.out.println(in.readLine()); // prints server time
}
}
}
TimeServer running on port 8080...
Served time to: 127.0.0.1
-- Terminal 2 (Client) --
Current server time: 2026-07-23 10:30:45
7. UDP with DatagramSocket
UDP is connectionless — you send a packet and the receiver may or
may not get it. Each message is a
DatagramPacket. There is no stream;
each send/receive is independent.
import java.net.*;
// UDP Server
public class UDPServer {
public static void main(String[] args) throws Exception {
DatagramSocket serverSocket = new DatagramSocket(9999);
byte[] receiveBuffer = new byte[1024];
System.out.println("UDP Server listening on port 9999...");
while (true) {
DatagramPacket receivePacket =
new DatagramPacket(receiveBuffer, receiveBuffer.length);
serverSocket.receive(receivePacket); // blocks until packet arrives
String message = new String(receivePacket.getData(), 0,
receivePacket.getLength());
System.out.println("Received: " + message);
// Send response back to sender
InetAddress clientAddr = receivePacket.getAddress();
int clientPort = receivePacket.getPort();
String reply = "ACK: " + message;
byte[] sendBuffer = reply.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendBuffer, sendBuffer.length,
clientAddr, clientPort);
serverSocket.send(sendPacket);
}
}
}
// UDP Client
public class UDPClient {
public static void main(String[] args) throws Exception {
DatagramSocket clientSocket = new DatagramSocket();
InetAddress serverAddr = InetAddress.getByName("localhost");
String message = "Hello UDP Server!";
byte[] sendBuffer = message.getBytes();
// Send the packet
DatagramPacket sendPacket =
new DatagramPacket(sendBuffer, sendBuffer.length, serverAddr, 9999);
clientSocket.send(sendPacket);
System.out.println("Sent: " + message);
// Receive the response
byte[] receiveBuffer = new byte[1024];
DatagramPacket receivePacket =
new DatagramPacket(receiveBuffer, receiveBuffer.length);
clientSocket.receive(receivePacket);
String response = new String(receivePacket.getData(), 0,
receivePacket.getLength());
System.out.println("Response: " + response);
clientSocket.close();
}
}
Sent: Hello UDP Server!
Response: ACK: Hello UDP Server!
8. URL Class
The URL class represents a Uniform
Resource Locator and can open a connection to read content from
it. This is the simplest way to fetch web content.
import java.net.*;
import java.io.*;
public class URLDemo {
public static void main(String[] args) throws Exception {
URL url = new URL("https://jsonplaceholder.typicode.com/posts/1");
System.out.println("Protocol: " + url.getProtocol()); // https
System.out.println("Host: " + url.getHost()); // jsonplaceholder...
System.out.println("Port: " + url.getPort()); // -1 (default)
System.out.println("Path: " + url.getPath()); // /posts/1
// Open connection and read content
System.out.println("\nFetching content...");
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}
Host: jsonplaceholder.typicode.com
Path: /posts/1
Fetching content...
{
"userId": 1,
"id": 1,
"title": "sunt aut facere..."
}
9. HttpURLConnection
HttpURLConnection provides control
over HTTP method, headers, request body, and response codes —
needed for REST API calls and form submissions.
GET Request
import java.net.*;
import java.io.*;
public class HttpGetDemo {
public static void main(String[] args) throws Exception {
URL url = new URL("https://jsonplaceholder.typicode.com/users/1");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
conn.setConnectTimeout(5000); // 5s connect timeout
conn.setReadTimeout(5000); // 5s read timeout
int responseCode = conn.getResponseCode();
System.out.println("Response Code: " + responseCode); // 200
if (responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line).append("\n");
}
System.out.println("Response body:\n" + response);
}
}
conn.disconnect();
}
}
POST Request
import java.net.*;
import java.io.*;
public class HttpPostDemo {
public static void main(String[] args) throws Exception {
URL url = new URL("https://jsonplaceholder.typicode.com/posts");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true); // enable sending a request body
// Write JSON request body
String jsonBody = "{\"title\":\"Java Post\",\"body\":\"Hello World\",\"userId\":1}";
try (OutputStream os = conn.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8")) {
writer.write(jsonBody);
writer.flush();
}
int responseCode = conn.getResponseCode();
System.out.println("POST Response Code: " + responseCode); // 201
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
conn.disconnect();
}
}
POST Response Code: 201
{
"id": 101,
"title": "Java Post",
"body": "Hello World",
"userId": 1
}
Modern alternative: Java 11 introduced
java.net.http.HttpClient which is
more modern, supports HTTP/2, and has a cleaner API. Prefer it
for new projects targeting Java 11+.
10. Common Networking Exceptions
| Exception | When It Occurs | Handling |
|---|---|---|
UnknownHostException |
Hostname cannot be resolved via DNS (typo, no internet, DNS failure). | Validate input; show user-friendly message; check connectivity. |
ConnectException |
Connection refused — server is not running or the port is closed. | Check that server is running; verify port number; firewall rules. |
SocketTimeoutException |
Connection or read exceeded the timeout set via
setSoTimeout().
|
Retry with backoff; increase timeout; inform user of slow response. |
BindException |
Server cannot bind to a port (already in use, or no permission for port < 1024). |
Try a different port; check running processes with
netstat.
|
SocketException |
General socket error — connection reset, broken pipe, network unreachable. | Parent of many network exceptions; log the message; gracefully close socket. |
import java.net.*;
import java.io.*;
public class RobustClientDemo {
public static void fetchData(String host, int port) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 3000); // 3s timeout
socket.setSoTimeout(5000); // 5s read timeout
try (socket;
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
System.out.println("Connected: " + in.readLine());
}
} catch (UnknownHostException e) {
System.err.println("Cannot resolve host: " + host);
} catch (ConnectException e) {
System.err.println("Connection refused on " + host + ":" + port);
} catch (SocketTimeoutException e) {
System.err.println("Timed out connecting to " + host);
} catch (IOException e) {
System.err.println("Network error: " + e.getMessage());
}
}
public static void main(String[] args) {
fetchData("localhost", 8080);
fetchData("nonexistent.invalid", 80);
fetchData("localhost", 9999); // nothing running
}
}
