Skip to content

Latest commit

 

History

History
200 lines (154 loc) · 8.81 KB

File metadata and controls

200 lines (154 loc) · 8.81 KB

🌐 Distributed-Java-App

A multi-threaded client-server application demonstrating distributed computing, concurrent task processing, and real-time network communication in Java.

The server accepts multiple simultaneous TCP connections via a thread pool, processes text commands, and logs all activity with timestamps. The Swing-based client provides a dark-themed terminal-style GUI with asynchronous message handling and color-coded output.


✨ Features

Server

Feature Description
Thread-Pool Concurrency Fixed-size ExecutorService handles up to 10 simultaneous clients without spawning unbounded threads
Command Processing 10 built-in commands: echo, upper, lower, reverse, count, length, replace, time, ping, help
Timestamped Logging All connections, commands, and responses logged to server.log with yyyy-MM-dd HH:mm:ss timestamps
Graceful Shutdown Shutdown hook cleanly terminates the thread pool and flushes logs on Ctrl-C
Client Tracking Each client gets a unique ID for log traceability
Null-Safe Reads Handles abrupt client disconnects without NullPointerException

Client

Feature Description
Dark Terminal UI Monospaced dark-themed Swing interface with color-coded messages
Async Reader Thread Background thread receives server messages without blocking the UI
Timestamped Messages Sent and received messages display [HH:mm:ss] timestamps
Status Bar Live connection status indicator at the bottom of the window
Clean Disconnect Window close handler sends goodbye and releases all resources
EDT-Safe All GUI operations run on the Event Dispatch Thread

Supported Commands

Command Example Result
echo <msg> echo hello Echo: hello
upper <msg> upper hello HELLO
lower <msg> lower HELLO hello
reverse <msg> reverse hello olleh
count <msg> count hello world Word count: 2
length <msg> length hello Length: 5
replace <old> <new> <msg> replace l r hello herro
time time Server date and time
ping ping pong
help help Lists all commands
bye bye Disconnects

📸 Screenshots

Screenshot 2024-04-24 at 11 07 42 AM Screenshot 2024-04-24 at 11 07 57 AM Screenshot 2024-04-24 at 11 08 32 AM Screenshot 2024-04-24 at 11 08 56 AM

🏗 Architecture

┌──────────────────┐         TCP :12345         ┌───────────────────┐
│   Client (Swing) │ ◄─────────────────────────► │      Server       │
│                  │    text commands / responses │                   │
│  ┌────────────┐  │                             │  ┌─────────────┐  │
│  │ GUI Thread │  │                             │  │ Main Thread  │  │
│  │ (EDT)      │  │                             │  │ accept()     │  │
│  └────────────┘  │                             │  └──────┬──────┘  │
│  ┌────────────┐  │                             │         │         │
│  │ Reader     │  │                             │  ┌──────▼──────┐  │
│  │ Thread     │  │                             │  │ ThreadPool  │  │
│  └────────────┘  │                             │  │ (10 workers)│  │
└──────────────────┘                             │  └──────┬──────┘  │
                                                 │         │         │
                                                 │  ┌──────▼──────┐  │
                                                 │  │ClientHandler│  │
                                                 │  │ (per client)│  │
                                                 │  └──────┬──────┘  │
                                                 │         │         │
                                                 │  ┌──────▼──────┐  │
                                                 │  │ server.log  │  │
                                                 │  └─────────────┘  │
                                                 └───────────────────┘

Key Design Decisions

  • Runnable over ThreadClientHandler implements Runnable and is submitted to an ExecutorService, not subclassed from Thread.
  • Shared synchronized logger — A single PrintWriter with synchronized access prevents log interleaving from concurrent handlers.
  • Null-safe read loopwhile ((line = reader.readLine()) != null) handles abrupt disconnects without crashing.
  • Background reader thread — The client reads server responses on a dedicated thread, preventing GUI freezes on readLine().
  • EDT compliance — All Swing UI mutations happen on the Event Dispatch Thread via SwingUtilities.invokeLater().
  • Try-with-resources — Server uses try-with-resources on the socket, reader, and writer for guaranteed cleanup.

🚀 Getting Started

Prerequisites

  • Java 11+ (uses var, text blocks, String.isBlank(), java.time)

Run

git clone https://github.com/shuddha2021/Distributed-Java-App.git
cd Distributed-Java-App

Terminal 1 — Start the server:

javac src/Server.java -d out
java -cp out Server

Terminal 2 — Start a client:

javac src/Client.java -d out
java -cp out Client

You can launch multiple client instances to test concurrent connections.

Quick Test

Once connected, type these commands in the client:

help
echo Hello, World!
upper distributed systems
reverse networking
count Java is awesome
time
ping
bye

📁 Project Structure

Distributed-Java-App/
├── src/
│   ├── Server.java    ← multi-threaded server with command processor and logging
│   └── Client.java    ← Swing GUI client with async reader and dark theme
├── .gitignore         ← ignores build artifacts, IDE files, and logs
└── README.md

🔧 Tech Stack

Concern Implementation
Language Java 11+
Networking java.net.ServerSocket, java.net.Socket — raw TCP sockets
Concurrency ExecutorService with fixed thread pool, AtomicInteger for client IDs
GUI Swing (JFrame, JTextPane, StyledDocument) with dark theme
Logging Timestamped file logging via java.time.LocalDateTime
I/O BufferedReader / PrintWriter with try-with-resources

🐛 Bugs Fixed from Original

Bug Fix
ServerThread extends Thread submitted to ExecutorService Changed to ClientHandler implements Runnable
readLine() null not checked — NullPointerException on client disconnect while ((line = reader.readLine()) != null) loop
Each thread opened its own FileWriter("server.log") — race condition Single shared PrintWriter with synchronized log method
Socket, reader, writer not closed in finally Try-with-resources on all I/O resources
Client created new BufferedReader on every sendCommand() Single reader on a background thread
GUI not built on EDT SwingUtilities.invokeLater() in main()
Debug System.out.println left in client Removed
No ExecutorService shutdown Shutdown hook added
count used .split(" ") (double spaces = empty tokens) Changed to .split("\\s+")

🤝 Contributing

Contributions welcome. Ideas for extension:

  • SSL/TLS encrypted connections
  • User authentication and session management
  • Persistent command history
  • File transfer protocol
  • REST API alongside raw sockets
  • Unit tests with JUnit

Fork the repo, create a feature branch, and submit a pull request.


📄 License

MIT