Understanding TCP Communication in Java with Socket Programming

TCP (Transmission Control Protocol) is a fundamental protocol that enables reliable communication between two computers over a network. In Java's standard library, two key classes facilitate TCP-based communication: the ServerSocket class for server-side operations and the Socket class for client-side operations.

The ServerSocket class binds to a specific port on the server machine and listens for incoming connection requests from clients. When a client connects, the server creates a corresponding Socket object to handle communication with that particular client.

Key Methods of the Client Socket

Practical Example: Transferring an Image File

Client Implementation

public class ImageClient { public static void main(String[] args) throws IOException { // Establish connection to the server at the specified IP and port Socket clientSocket = new Socket("127.0.0.1", 8888);

    // Create input stream to read the source image file
    FileInputStream fileIn = new FileInputStream("D:\\images\\photo.png");
    
    // Get the output stream to send data to the server
    OutputStream output = clientSocket.getOutputStream();
    byte[] buffer = new byte[1024];
    int bytesRead;
    
    // Transfer the file in chunks
    while ((bytesRead = fileIn.read(buffer)) != -1) {
        output.write(buffer, 0, bytesRead);
    }
    
    // Signal the server that file transfer is complete
    clientSocket.shutdownOutput();
    
    // Receive server acknowledgment
    InputStream input = clientSocket.getInputStream();
    String clientIP = clientSocket.getInetAddress().getHostAddress();
    bytesRead = input.read(buffer);
    System.out.println("From server " + clientIP + ": " + new String(buffer, 0, bytesRead));
    
    // Clean up resources
    fileIn.close();
    clientSocket.close();
}

}


</div>### Server Implementation (Single-Threaded)

<div>```
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ImageServer {
    public static void main(String[] args) throws IOException {
        // Initialize server socket on the specified port
        ServerSocket serverSocket = new ServerSocket(8888);
        
        // Accept incoming client connection
        Socket clientConnection = serverSocket.accept();
        
        // Get input stream to receive data from client
        InputStream input = clientConnection.getInputStream();
        
        // Prepare destination directory
        File destinationDir = new File("D:\\received");
        if (!destinationDir.exists()) {
            destinationDir.mkdirs();
        }
        
        // Generate unique filename for the incoming image
        String fileName = "received_" + System.currentTimeMillis() + 
                          "_" + (int)(Math.random() * 999999) + ".png";
        
        // Create output stream to write received data
        FileOutputStream fileOut = new FileOutputStream(
            destinationDir + File.separator + fileName
        );
        
        byte[] buffer = new byte[1024];
        int bytesReceived;
        
        // Receive and save the image data
        while ((bytesReceived = input.read(buffer)) != -1) {
            fileOut.write(buffer, 0, bytesReceived);
        }
        
        // Send acknowledgment back to client
        OutputStream output = clientConnection.getOutputStream();
        output.write("Transfer complete".getBytes());
        
        // Release resources
        clientConnection.close();
        fileOut.close();
    }
}

The single-threaded approach above has a significant drabwack: only one client can transfer a file at a time. If multiple clients attempt simultaneous connections, subsequent clients must wait until the current transfer finishes. To resolve this, we implement concurrent processing using thread pools.

Upload Handler (Runnable Task)

public class FileUploadHandler implements Runnable { private Socket connectionSocket;

public FileUploadHandler(Socket socket) {
    this.connectionSocket = socket;
}

@Override
public void run() {
    FileOutputStream fileWriter = null;
    try {
        InputStream receiver = connectionSocket.getInputStream();
        
        // Verify destination directory exists
        File storageDirectory = new File("D:\\received");
        if (!storageDirectory.exists()) {
            storageDirectory.mkdirs();
        }
        
        // Generate unique filename with timestamp and random suffix
        String targetFile = "image_" + System.currentTimeMillis() + 
                           "_" + (int)(Math.random() * 999999) + ".png";
        
        // Initialize output stream to save file
        fileWriter = new FileOutputStream(
            storageDirectory + File.separator + targetFile
        );
        
        byte[] buffer = new byte[1024];
        int dataChunk;
        
        // Write received bytes to file
        while ((dataChunk = receiver.read(buffer)) != -1) {
            fileWriter.write(buffer, 0, dataChunk);
        }
        
        // Confirm successful receipt to client
        OutputStream sender = connectionSocket.getOutputStream();
        sender.write("Success: File received".getBytes());
        
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // Ensure proper resource cleanup
        try {
            if (fileWriter != null) {
                fileWriter.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}


</div>### Concurrent Server with Thread Pool

<div>```
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConcurrentServer {
    public static void main(String[] args) throws IOException {
        // Create server socket bound to port 8888
        ServerSocket serverSocket = new ServerSocket(8888);
        
        // Create a thread pool to handle multiple clients
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        
        System.out.println("Server started, waiting for connections...");
        
        // Continuously accept client connections
        while (true) {
            Socket clientSocket = serverSocket.accept();
            System.out.println("New client connected: " + 
                             clientSocket.getInetAddress().getHostAddress());
            
            // Submit the client handler to the thread pool
            threadPool.execute(new FileUploadHandler(clientSocket));
        }
    }
}

Tags: java socket-programming tcp network-programming server-socket

Posted on Sun, 10 May 2026 13:35:38 +0000 by parth