Chapter 3
Networking in Java
Java Networking enables Java programs to communicate and exchange data
across networks, whether local or global.
This capability is fundamental for building distributed applications and
modern software that interacts with other systems.
Key Concepts and Components:
[Link] Package:
The core of Java networking is the [Link] package, which provides classes and
interfaces for handling various networking tasks, including:
IP Addresses: Represented by InetAddress (for both IPv4 and IPv6).
URLs and URIs: URL and URI classes for locating and accessing network
resources.
Sockets: Socket and ServerSocket classes for client-server communication
using TCP (connection-oriented) and DatagramSocket/DatagramPacket for
UDP (connectionless).
URL Connections: URLConnection and HttpURLConnection for
establishing communication links with URLs, especially for HTTP.
Client-Server Architecture:
A common model in Java networking where:
•Server: Listens for and accepts connections from clients, then processes their
requests. Uses ServerSocket to listen on a specific port.
•Client: Initiates communication by connecting to the server's IP address and
port using a Socket.
Socket Programming:
• TCP (Stream Sockets): Provides reliable, connection-oriented communication,
ensuring data delivery in order and without loss. Used for applications like HTTP,
FTP.
• UDP (Datagram Sockets): Offers connectionless communication, sending data in
packets (datagrams) without guaranteed delivery or order. Suitable for applications
where speed is prioritized over reliability, like streaming
Example of Client-Server Communication (TCP):
Server-side:
import [Link].*;
import [Link].*;
public class SimpleServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(12345); // Listen on
port 12345
[Link]("Server listening on port 12345...");
Socket clientSocket = [Link](); // Wait for a client
to connect
[Link]("Client connected: " +
[Link]());
Cont…
// Get input and output streams for communication
BufferedReader in = new BufferedReader(new InputStreamReader([Link]()));
PrintWriter out = new PrintWriter([Link](), true);
String message = [Link](); // Read message from client
[Link]("Received from client: " + message);
[Link]("Hello from Server!"); // Send response to client
[Link]();
[Link]();
}
}
Client-side:
import [Link].*;
import [Link].*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 12345); // Connect to server on
localhost:12345
[Link]("Connected to server.");
// Get input and output streams for communication
PrintWriter out = new PrintWriter([Link](), true);
BufferedReader in = new BufferedReader(new
InputStreamReader([Link]()));
[Link]("Hello from Client!"); // Send message to server
String response = [Link](); // Read response from server
[Link]("Received from server: " + response);
[Link]();
}
}
Manipulating a file on web server in java
Manipulating files on a web server using Java typically involves server-side programming, where a
Java application running on the server handles file operations based on client requests.
This can be achieved through various approaches:
1. Using Java Servlets or Spring Boot:
Servlets: Java Servlets are a core technology for building web applications. They run within a web
server (like Apache Tomcat) and can receive HTTP requests from clients.
You can use Java's [Link] and [Link] APIs within a servlet to perform file operations (reading,
writing, deleting, creating directories) on the server's file system.
Spring Boot: Spring Boot simplifies the creation of stand-alone, production-grade Spring-based
applications.
It often uses embedded web servers (like Tomcat or Jetty) and provides a powerful framework for
handling web requests and interacting with the server's file system.
Example (Conceptual Servlet):
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@WebServlet("/fileManipulator")
public class FileManipulatorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = [Link]("action");
String fileName = [Link]("fileName");
String content = [Link]("content"); // For writing
String serverPath = getServletContext().getRealPath("/WEB-INF/files/"); //
Example path
File targetFile = new File(serverPath, fileName);
Cont..
if ("write".equals(action)) {
try (FileWriter writer = new FileWriter(targetFile)) {
[Link](content);
[Link]().println("File written successfully.");
} catch (IOException e) {
[Link]().println("Error writing file: " + [Link]());
}
} else if ("read".equals(action)) {
try (BufferedReader reader = new BufferedReader(new
FileReader(targetFile))) {
StringBuilder fileContent = new StringBuilder();
String line;
while ((line = [Link]()) != null) {
[Link](line).append("\n");
}
[Link]().println("File content:\n" + [Link]());
} catch (IOException e) {
[Link]().println("Error reading file: " + [Link]());
}
}
// Add more actions like delete, create directory, etc.
}
Using Java's Simple Web Server (JDK 18+):
Java 18 introduced a built-in SimpleFileServer for serving static files.
While primarily for static content, you can potentially extend or integrate with it to add dynamic
file manipulation capabilities if your use case is simple and doesn't require a full-fledged web
framework.
3. Direct File I/O with Socket Programming (Less Common for
Web Servers):
For very specific, low-level file transfer or manipulation, you could implement custom client-
server communication using Java sockets.
This would involve a Java server application listening for connections and a client application
sending commands and file data.
This is typically more complex than using servlets or frameworks for general web server file
manipulation.
Security Considerations:
Access Control:
Carefully manage permissions for files and directories on the server to prevent unauthorized access
or modification.
Input Validation:
Validate all client-provided input (filenames, content) to prevent directory traversal attacks or
malicious code injection.
Error Handling:
Implement robust error handling to gracefully manage file-related exceptions and provide
informative feedback to the client.
Establishing a Simple Server Using Stream Sockets
Establishing a simple server using stream sockets in Java involves the following
steps:
Create a ServerSocket: This object listens for incoming client connections on a
specified port number.
ServerSocket serverSocket = new ServerSocket(portNumber);
Listen for Client Connections:
The accept() method of the ServerSocket blocks until a client attempts to connect. When a connection
is established, it returns a Socket object representing the connection with that specific client.
Socket clientSocket = [Link]();
Establish I/O Streams: Obtain InputStream and OutputStream objects from the clientSocket to send
and receive data with the connected client.
Wrap these streams with appropriate reader/writer classes for easier data handling (e.g.,
BufferedReader, PrintWriter).
BufferedReader in = new BufferedReader(new InputStreamReader([Link]()));
PrintWriter out = new PrintWriter([Link](), true); // true for auto-flushing
• Communicate with the Client: Use the established I/O streams to exchange data. For example, read
lines from the client and send responses back.
String inputLine;
while ((inputLine = [Link]()) != null) {
[Link]("Client says: " + inputLine);
[Link]("Server echoes: " + inputLine); // Send response back to client
if ([Link]("bye")) {
break; // Exit loop on specific input
}
}
Close Resources: After communication is complete, close the clientSocket, ServerSocket, and
associated streams to release system resources.
This should typically be done in a finally block to ensure closure even if exceptions occur.
[Link]();
[Link]();
[Link]();
[Link]();
Example Server Structure:
import [Link].*;
import [Link].*;
public class SimpleServer {
public static void main(String[] args) {
int portNumber = 12345; // Choose an available port
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
[Link]("Server started on port " + portNumber);
while (true) { // Server listens indefinitely for clients
Socket clientSocket = [Link](); // Blocks until a client
connects
[Link]("Client connected: " +
[Link]());
// Handle client communication in a }
separate thread for multiple clients [Link]("Client
new Thread(() -> { disconnected: " +
try ( [Link]());
PrintWriter out = new } catch (IOException e) {
PrintWriter([Link] [Link]("Error handling
am(), true); client: " + [Link]());
BufferedReader in = new } finally {
BufferedReader(new try {
InputStreamReader([Link] [Link]();
tStream())) } catch (IOException e) {
) { [Link]("Error closing
String inputLine; client socket: " + [Link]());
while ((inputLine = [Link]()) != }
null) { }
[Link]("Received from }).start();
client " + }
[Link]() + ": " + } catch (IOException e) {
inputLine); [Link]("Could not listen
[Link]("Server received: " + on port " + portNumber + ": " +
inputLine); // Echo back to client [Link]());
if ([Link]("bye")) }
{ }
break; }
}
Establishing a Simple Client Using Stream Sockets in java
Establishing a simple client using stream sockets in Java involves several key
steps to connect to a server and exchange data.
Create a Socket object.
This object represents the client's end of the connection.
You need to specify the server's IP address (or hostname) and the port
number the server is listening on.
import [Link];
import [Link].*;
// ... inside a method or constructor
String serverAddress = "localhost"; // Or the
server's IP address
int portNumber = 12345; // The port the server
is listening on
Socket clientSocket = new Socket(serverAddress,
portNumber);
Cont..
Once connected, you need streams to send and receive data.
[Link]() provides an OutputStream to send data to the server.
[Link]() provides an InputStream to receive data from the
server.
Perform Communication
Use the out and in objects to send and receive data according to the server's
protocol.
[Link]("Hello from the client!"); // Send a message
String serverResponse = [Link](); // Read a response
[Link]("Server says: " + serverResponse);
Close Resources.
It is crucial to close the streams and the socket when the communication is complete to release
system resources.
This should typically be done in a finally block to ensure they are closed even if exceptions
occur.
try {
// ... communication code ...
} finally {
if (out != null) [Link]();
if (in != null) [Link]();
if (clientSocket != null) [Link]();
}
Client/Server Interaction With Stream Socket Connection in java
Client-server interaction with stream socket connections in Java involves establishing
a two-way communication channel between a client and a server using Socket and
ServerSocket classes.
Server-Side Steps:
Create a ServerSocket: The server initiates by creating a ServerSocket object,
specifying a port number on which it will listen for incoming client connections
ServerSocket serverSocket = new ServerSocket(portNumber);
Cont..
Listen for and Accept Connections: The server then enters a loop, waiting for
client connection requests using the accept() method of the ServerSocket.
This method blocks until a client attempts to connect and, upon successful
connection, returns a Socket object representing the connection to that specific
client.
Socket clientSocket = [Link]();
Establish I/O Streams:
Once a client connects, the server obtains input and output streams from the clientSocket to facilitate data
exchange.
InputStreamReader and OutputStreamWriter wrapped in BufferedReader and BufferedWriter are commonly
used for text-based communication.
BufferedReader in = new BufferedReader(new InputStreamReader([Link]()));
PrintWriter out = new PrintWriter([Link](), true); // true for auto-flush
Cont..
Communicate: The server then reads data from the client using the input stream and sends data
to the client using the output stream, following an agreed-upon communication protocol.
Close Resources: After communication is complete, the server closes the input/output streams and
the clientSocket to release resources.
Client-Side Steps:
Create a Socket: The client initiates the connection by creating a Socket
object, providing the server's IP address (or hostname) and the port number
it's listening on.
Socket clientSocket = new Socket("serverHostname", portNumber);
Establish I/O Streams:
Similar to the server, the client obtains input and output streams from its
clientSocket to send and receive data.
PrintWriter out = new
PrintWriter([Link](), true);
BufferedReader in = new BufferedReader(new
InputStreamReader([Link]()));
Cont..
Communicate: The client sends requests to the server using its output stream and receives
responses using its input stream, adhering to the defined protocol.
Close Resources: Upon completion of communication, the client closes its input/output
streams and the clientSocket.
Key Concepts:
ServerSocket: Used on the server side to listen for and accept client connections.
Socket: Represents an endpoint of a two-way communication link, used by both client and
server for actual data exchange.
Input/Output Streams: Provide the mechanism for reading data from and writing data to
the connected socket.
Port Number: A numerical identifier that distinguishes different applications or services
running on a server.
IP Address/Hostname: Identifies the server on the network.
Connectionless Client/Server Interaction With Datagram in java
Connectionless client/server interaction in Java using datagrams relies on the User Datagram
Protocol (UDP) and the [Link] and [Link] classes.
This approach differs from connection-oriented (TCP) communication by not establishing a
persistent connection between client and server.
Key characteristics:
No Handshake: There is no initial connection establishment phase (like the
three-way handshake in TCP).
Packet-based: Data is sent in independent units called datagrams, encapsulated
within DatagramPacket objects.
Unreliable Delivery: Delivery of datagrams is not guaranteed; packets may be
lost, duplicated, or arrive out of order.
Faster and Lower Overhead: The absence of connection management
overhead makes UDP generally faster and more efficient for certain
applications.
Client-Server Interaction Steps:
Server:
Create a DatagramSocket: Bind it to a specific port number on the local machine to
listen for incoming datagrams.
DatagramSocket serverSocket = new DatagramSocket(portNumber);
Create a DatagramPacket for receiving: Specify a byte array buffer to hold the
incoming data.
byte[] receiveBuffer = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer,
[Link]);
Cont..
Receive a datagram: Block until a datagram arrives, filling the receivePacket
with data and sender information.
[Link](receivePacket);
Process the received data: Extract the data from the receivePacket's buffer.
Optionally, send a reply: Create a new DatagramPacket with the reply data,
targeting the client's address and port obtained from the receivePacket.
Cont..
InetAddress clientAddress = [Link]();
int clientPort = [Link]();
byte[] sendBuffer = "Reply from server".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuffer,
[Link], clientAddress, clientPort);
[Link](sendPacket);
Repeat: Continue listening for and processing incoming datagrams.
Close the DatagramSocket: When done, release the port.
[Link]();
Client:
Create a DatagramSocket: Can be bound to any available local port.
DatagramSocket clientSocket = new DatagramSocket();
Prepare data to send: Convert the data into a byte array.
Create a DatagramPacket for sending: Specify the data, its length, the server's IP address, and the
server's port number.
InetAddress serverAddress = [Link]("localhost"); // or
server's actual IP
int serverPort = portNumber;
byte[] sendBuffer = "Hello from client".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuffer,
[Link], serverAddress, serverPort);
Cont..
Send the datagram
[Link](sendPacket);
Optionally, receive a reply: Create a DatagramPacket for receiving and call [Link]().
byte[] receiveBuffer = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer,
[Link]);
[Link](receivePacket);
// Process received data
Close the DatagramSocket
[Link]();