A real-time, terminal-based chat application built from scratch using Java Sockets and Multithreading. No frameworks, no libraries — just pure Java networking.
TerminalTalk allows multiple users to connect to a central server, chat in a public room, send private messages, and see who is online — all from the command line.
I wanted to go beyond just reading about the OSI model and TCP/IP in textbooks. This project forced me to actually implement those concepts — opening sockets, managing byte streams, handling concurrent connections, and designing my own application-layer protocol. Every line of code in this project maps directly to a Computer Networks concept.
TerminalTalk follows the Client-Server Architecture, one of the most fundamental models in computer networking.
┌──────────────┐ TCP Connection ┌──────────────────────────┐
│ Client 1 │ ◄────────────────────────────► │ │
│ (Terminal) │ │ │
└──────────────┘ │ │
│ TerminalTalk Server │
┌──────────────┐ TCP Connection │ │
│ Client 2 │ ◄────────────────────────────► │ - Accepts connections │
│ (Terminal) │ │ - Manages user list │
└──────────────┘ │ - Routes messages │
│ - Handles commands │
┌──────────────┐ TCP Connection │ │
│ Client 3 │ ◄────────────────────────────► │ │
│ (Terminal) │ │ │
└──────────────┘ └──────────────────────────┘
- Server starts and opens a
ServerSocketon port8080, waiting for incoming connections. - Client connects by creating a
Socketpointed at the server's IP and port. - TCP Handshake happens automatically under the hood (SYN → SYN-ACK → ACK), establishing a reliable connection.
- Server spawns a new thread (via a Thread Pool) dedicated to this client. This thread runs a
ClientHandlerthat reads and writes messages for that specific user. - Client runs two threads of its own:
- Listener Thread — constantly reads incoming messages from the server and prints them.
- Main Thread — reads keyboard input and sends it to the server.
- Messages are routed by the server: broadcast to all users, or sent privately to one user based on the command.
- On disconnect, the server removes the user from the active list and notifies everyone.
TerminalTalk/
│
├── Server.java # The central server — listens, accepts, and manages connections
├── ClientHandler.java # Runs on a separate thread for each connected user
├── Client.java # The program users run to connect and chat
└── README.md # You are here
| File | Responsibility |
|---|---|
Server.java |
Opens a ServerSocket on port 8080. Maintains a thread-safe map of active users (ConcurrentHashMap). Provides helper methods for broadcasting and private messaging. |
ClientHandler.java |
Implements Runnable. Handles username registration, message parsing, command execution (/msg, /users, /quit), and clean disconnection. |
Client.java |
Connects a Socket to the server. Uses a daemon listener thread for incoming messages and the main thread for user input. |
This project directly implements the following concepts from a Computer Networks course:
The entire application is built on the Client-Server paradigm. The server is a passive entity that listens for requests, while clients are active entities that initiate connections. This is the same model used by HTTP, FTP, SMTP, and most internet services.
All communication uses TCP (Transmission Control Protocol) via Java's Socket and ServerSocket classes.
Why TCP and not UDP?
- TCP guarantees reliable, ordered delivery of data. In a chat app, we cannot afford messages being dropped or arriving out of order.
- TCP provides flow control and error detection through checksums and acknowledgments.
- UDP would be faster but unreliable — suitable for video streaming or gaming, not text messaging.
Under the hood, every connection begins with the TCP 3-Way Handshake:
Client Server
│──── SYN ─────────────►│
│◄─── SYN-ACK ──────────│
│──── ACK ─────────────►│
│ │
│ Connection Established
A socket is the endpoint for communication between two machines. It is identified by an IP Address + Port Number pair.
ServerSocket(8080)— binds the server to port 8080 and listens for connections.Socket("localhost", 8080)— the client creates a socket connecting to the server.- Each socket provides an
InputStream(to read data) and anOutputStream(to write data), forming a full-duplex communication channel.
Port 8080 is used to uniquely identify this application on the machine. The OS uses port numbers to demultiplex incoming packets — directing web traffic (port 80) to the browser and our chat traffic (port 8080) to TerminalTalk.
The commands /msg, /users, and /quit form a custom Application-Layer Protocol. Just like HTTP defines GET and POST, our protocol defines rules for how the client and server exchange information:
| Command | Protocol Action |
|---|---|
| Plain text | Server broadcasts to all connected clients |
/msg [user] [text] |
Server performs a unicast — sends only to the target user |
/users |
Server responds with the current list of active connections |
/quit |
Client signals graceful termination; server cleans up resources |
A real-world server must handle thousands of simultaneous connections. A single-threaded server can only serve one user at a time — everyone else waits in line.
We solve this using a Thread Pool (ExecutorService):
┌─── Thread 1 ──► ClientHandler (User A)
│
Server.accept() ──────┼─── Thread 2 ──► ClientHandler (User B)
│
└─── Thread 3 ──► ClientHandler (User C)
When multiple threads access shared data (like the list of active users), race conditions can occur. We prevent this using ConcurrentHashMap, which allows safe concurrent reads and writes without explicit locking.
- Java JDK 8 or higher installed on your machine.
- Verify by running:
java -version
Open a terminal and navigate to the project folder:
cd "C:\Users\kkuna\Desktop\Computer_netwroks project"
javac Server.java ClientHandler.java Client.javaRun the server in one terminal window:
java ServerYou should see:
===========================================
TerminalTalk Server is starting up...
===========================================
[SERVER] Listening on port 8080...
[SERVER] Waiting for users to connect.
Open 2 or more additional terminal windows and run:
cd "C:\Users\kkuna\Desktop\Computer_netwroks project"
java ClientEach client will be prompted for a username. Once connected, start chatting!
> Hello everyone! # broadcasts to all users
> /msg Alice hey, how are you? # private message to Alice
> /users # see who is online
> /quit # disconnect
To chat across two different computers on the same network:
- Find the server machine's local IP address:
ipconfig # Windows ifconfig # Mac/Linux
- In
Client.java, changeSERVER_ADDRESSfrom"localhost"to the server's IP (e.g.,"192.168.1.5"). - Recompile and run the client on the other machine.
| Feature | Description |
|---|---|
| Global Chat | Any text message is broadcast to all connected users |
| Private Messaging | /msg [username] [message] sends a direct message to one user |
| Active Users List | /users displays everyone currently online |
| Unique Usernames | Server enforces unique names — no duplicates allowed |
| Join/Leave Notifications | Everyone is notified when a user joins or leaves |
| Graceful Disconnect | /quit safely removes the user and closes the connection |
| Crash-Safe | If a client's terminal is closed abruptly, the server handles it without crashing |
- How TCP sockets establish and maintain reliable connections between machines.
- The importance of multithreading in server design — without it, only one user can connect at a time.
- Why thread safety matters: using
ConcurrentHashMapto prevent data corruption when multiple threads modify shared state. - How to design a simple application-layer protocol with defined message formats and commands.
- The difference between blocking I/O (used here) and non-blocking I/O (Java NIO), and the trade-offs of each.
- Add chat rooms / channels (like IRC's
#general,#random) - Message timestamps
- File sharing between users
- Encryption using Java's
javax.net.ssl.SSLSocketfor secure communication - A graphical UI using JavaFX
- Language: Java (JDK 8+)
- Networking:
java.net.Socket,java.net.ServerSocket - Concurrency:
java.util.concurrent.ExecutorService,ConcurrentHashMap - No external libraries or frameworks
This project was built as a Computer Networks academic project. Feel free to use it as a reference or learning resource.