Reviewed-on: #1 100/100 (with leniency)
Network File-Sharing chat System (Java)
Overview
This project is a multi-client network chat system with file sharing, implemented using Java sockets, MUltithreading and Object Serialization. Clients connect to a central server and can:
- send public chat message
- send private messages
- request the list of online users
- transfer files to other users
communication between client and server is implemented using Java Object Streams(ObjectInputStream / ObjectOutputStream) so that structured objects can be transferred directly over the network.
Architecture
- ChatServer opens a
ServerSocketand waits for connections. - Each connecting client gets its own ClientSession thread.
- A shared UserManager tracks who's online and routes messages.
- Everything is exchanged as serialized objects (
ChatMessage/FileMessage).
Client → Socket → Server → ClientSession (thread) → UserManager → Broadcast/Route → Clients
Message Protocol
Two serializable classes carry everything over the wire:
- ChatMessage – text-based: logins, public/private messages, user-list requests, server replies.
- FileMessage – file transfers, carrying the file as a
byte[].
MessageType is an enum (LOGIN, LOGIN_SUCCESS, LOGIN_FAILED, PUBLIC_MESSAGE, PRIVATE_MESSAGE, USER_LIST, …) so both sides agree on what each message means.
Package Structure
com.university.chat
├── common → shared message classes (ChatMessage, FileMessage, MessageType)
├── server → server-side logic
└── client → client application
common
Already complete — these define the protocol and don't need any changes.
server
- ChatServer – entry point. Opens the server socket and creates a
ClientSessionper client. - ClientSession – one thread per client. Handles login, reads incoming messages, and dispatches them (broadcast, private message, user list, file transfer).
- UserManager – thread-safe registry of online users (
ConcurrentHashMap<String, ClientSession>). Already complete. - FileManager – manages per-user folders on disk (
server_data/<username>/sentandreceived). Already complete.
client
- chatClient – entry point. Connects to the server, logs in, starts a listener thread, and runs the input loop for user commands.
- ServerListener – background thread that continuously reads and displays messages/files coming from the server.
- TransferProgress – small helper that prints a progress bar during file uploads. Already complete.
Client Commands
/msg <username> <message> → private message
/users → list online users
/sendfile <username> <filepath> → send a file
<anything else> → public message
File Transfer Flow
- Client reads the file and converts it to
byte[]. - It's wrapped in a
FileMessageand sent to the server. - The server saves a copy (in
sent/for the sender,received/for the receiver) and forwards it to the recipient.
Threading Model
- Server: one
ClientSessionthread per connected client. - Client: main thread handles user input, a
ServerListenerthread handles incoming messages — so you can chat and receive at the same time.
Your Task
Several core pieces are left as TODOs for you to implement. Follow the comments in each file alongside the structure mentioned above to complete them.
| File | What to implement |
|---|---|
Server/ChatServer.java |
Pick a port, create a shared UserManager, open the server socket, accept clients in a loop, and create a ClientSession thread per client. |
Server/ClientSession.java |
Set up object streams in the constructor; handle login (success/failure); receive messages in a loop and dispatch ChatMessage/FileMessage; broadcast, private message, and user-list logic; remove user on disconnect; forward files. |
Client/chatClient.java |
Connect to the server, set up streams, log in, start ServerListener, and implement the command loop (/msg, /users, /sendfile, plain messages). |
Client/ServerListener.java |
Continuously read objects from the server and print chat messages / file-received notifications. |
Tips:
- Always create the
ObjectOutputStreambefore theObjectInputStreamon both ends — this avoids a stream-handshake deadlock. - Don't forget
out.flush()afterwriteObject(...). - Test with two or more client instances to verify broadcasting, private messages, and file transfer all work correctly.
Running multiple clients in IntelliJ
- Click the ⋮ icon next to the run button → Edit Configurations
- Open Modify options (Alt+M)
- Enable Allow multiple instances (Alt+U)
Optional Bonus: JavaFX UI
If you want to go further replace the console client with a simple JavaFX GUI (chat window, online-user list, file-send button, etc.).
-
Add the JavaFX dependencies to your
pom.xml— for Maven:<dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>21</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>21</version> </dependency>You'll also need the
javafx-maven-pluginto run the app from Maven. -
Create a JavaFX entry point, e.g.
Client/ChatClientApp.java, extendingjavafx.application.Applicationand implementingstart(Stage stage). This becomes your new launch class instead of (or alongside)chatClient. -
Reuse your existing socket/streams logic — just move the "send" actions to button handlers and update the UI from
ServerListenerusingPlatform.runLater(...)(since UI updates must happen on the JavaFX Application Thread).
This part is completely optional and won't affect your core grade — just a fun way to practice connecting a GUI to networking code and multithreading.