A simple project aimed to build a client-server application on top of TCP sockets.
The users can:
- Create groups
- Join groups
- Chat
- Share files
- Download files
|
|
Task chooser interface | Join group interface |
|
|
Chat interface | File upload interface |
|
|
File download interface |
- Linux (Tested on Ubuntu 22.04.1 LTS)
- C++ 17
- Curses library
- OpenSSL library
- Nlohmann Json library
Execute the commands at the root of the repository.
mkdir build
cd build
cmake ..
make
This will check for all the dependencies and generate the client and server binaries.
The client and server communicate via simple message passing through TCP. The messages are considered to be a stream of bytes. A sample message structure is as follows:
A message consists of three parts:
- Code: Predefined 1 byte mesaage codes used by both client and server. See defined codes
- Length: Next 4 bytes together determine the length of the json data that follows it.
- Json data: Variable length field that contains any additional message that is to be sent in json format. When no additional data is to be sent this field contains an empty json object.
The client is a multithreaded application which used two pthreads.
One thread is responsible for displaying the information on the terminal window and pushing messages to socket when required.
The other thread continuously listenes for incoming messages on the socket.
On every message received (except chat messages), it pushes the message to a thread-safe queue.
(A communication channel between the two threads. Thread-safe queue)
When a client is run, it creates a directory study-collab-client. The file .logs.txt inside this contains all the log data for the client.
The sub-directory downloads contains all the downloaded files from the server into specific sub-directories for each group. A sub-directory for a group has title "group_id-group_name"
- The client program sends the LOGIN_REQUEST code with email and password in json data.
- The server responds with either LOGIN_SUCCESS or LOGIN_FAILED.
- The client program sends the CREATE_GROUP_REQUEST code with group_name in json data.
- The server responds with either CREATE_GROUP_SUCCESS or CREATE_GROUP_FAILED. In case of successful creation it also sends the group_id of the created group.
- The client program first sends the REQUEST_NON_PARTICIPATING_GROUPS message to the server.
- The server responds with a list of all groups the client is not a part of in a json array format with code REPLY_NON_PARTICIPATING_GROUPS.
- The client then choose a group and sends the REQUEST_JOIN_GROUP code with group_id in the json data.
- The server responds with either JOIN_GROUP_SUCCESS or JOIN_GROUP_FAILED code.
Chats feature only works for groups. Chats are not stored on the server.
As the server receives a chat from some client, it immediately forwards the chat to all the members of the group currently online.
As a client recieves a chat message (identified by code NEW_MESSAGE) it stores the chat in ChatDB.
For entering a chat room, the client:
- Performs the REQUEST_PARTICIPATING_GROUPS negotiation
- Loads the older chats form ChatDB
- Adds a listener to ChatDB for listening to new incoming chats
- Waits for user input to send a chat with code SEND_MESSAGE
- On receiving input from user, sends a chat and goes back to 4
Files can be shared only in groups. Files are transferred between hosts in a chunked format. Each chunk (max size = 2046 bytes) is encoded in a Base64 format.
For sharing a file, the client:
- Performs the REQUEST_PARTICIPATING_GROUPS negotiation
- Enters the path of the file to be shared
- Breaks the file into chunks of size 2046 bytes (except the last one), encodes it into Base64 format and sends it with code SAVE_FILE and json data containing chunk (the Base64 encoding) and last indicaing if it is the last chunk.
- Server responds with either SAVE_FILE_SUCCESS or SAVE_FILE_FAILED code
For downloading a file, the client:
- Performs the REQUEST_PARTICIPATING_GROUPS negotiation
- Sends a message with code REQUEST_FILES_LIST and group_id in json data
- Sends a message with code REQUEST_FILE and group_id and filename in json data
- Server responds with code SAVE_FILE and sends the file in chunks encoded in Base64 format
- The file is decoded and saved into a specific sub-directory
The server is a multithreaded application with each pthread handling one client.
The server waits for new connections. On receiving a new connection, it creates a pthread and starts listening to incoming messages.
As a new message is recieved it processes the message and immediately responds to it.
The server uses a in-memory database to store all information about users, groups and files shared.
When the server is run, a directory study-collab-server is created. The file .logs.txt inside this contains all the log data for the server.
The store sub-directory contains all the uploaded files arranged into sub-folders identified by their group_id.