Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CS3205 Assignment 2 - Multi-Client Chat Server

Overview

This project implements a multi-client chat application in C++ using TCP sockets. The system supports real-time communication between users and is designed to explore different concurrency models for handling multiple simultaneous client connections.

The system consists of three main components:

  • Chat Server – Manages authenticated client connections and message routing.
  • Discovery Server – Handles user registration and credential validation.
  • Chat Client – Provides a terminal-based interface for users to interact with the chat system.

The assignment also includes performance benchmarking to compare different server concurrency approaches under load and stress conditions.


System Architecture

High-Level Workflow

  1. Client registers/logs in via the Discovery Server (port 8000).
  2. Discovery Server validates credentials.
  3. Client connects to the Chat Server (port 8080).
  4. Chat Server manages message routing between active users.
  5. Monitoring module collects performance metrics during benchmarking.

Server Implementations

The chat server is implemented using three different concurrency models:


1. Fork-Based Server (server_fork)

Approach:

  • Uses the fork() system call.
  • Creates a new child process for each client connection.
  • Uses pipes for inter-process communication (IPC) between child processes and the parent process.
  • Parent process acts as a message router, reading from child pipes and forwarding to the appropriate recipient pipe.

Key Characteristics:

  • Process-level isolation ensures fault containment.
  • Higher VmRSS memory overhead (each child is counted separately), but PSS remains low due to copy-on-write page sharing.
  • No shared-state complexity within children — each child handles exactly one client.

Expected Behavior Under Load:

  • Increased VmRSS with client count, PSS grows more slowly.
  • Higher latency variance due to fork() cost per connection.
  • Stable isolation between clients.

2. Thread-Based Server (server_pthread)

Approach:

  • Uses pthread_create() to spawn a new thread per client.
  • All threads share the same address space.
  • Shared state (active users, socket map) protected by a single pthread_mutex_t.

Key Characteristics:

  • Shared memory model allows direct in-process message forwarding.
  • Lower memory overhead than fork-based approach.
  • Faster context switching compared to processes.
  • Mutex contention can become a bottleneck at high concurrency.

Expected Behavior Under Load:

  • Low and stable latency.
  • Flat memory usage as threads share the process heap.
  • CPU scales with client count; mutex lock contention may cause spikes.

3. Non-Blocking Event-Driven Server (server_select)

Approach:

  • Uses select() to monitor multiple socket descriptors for readiness.
  • Single process and single thread handles all client sockets.
  • Event-driven I/O model — only acts when a socket is ready.

Key Characteristics:

  • No per-client thread or process overhead.
  • Lowest memory consumption of the three implementations.
  • Hard limit of 30 simultaneous clients (MAX_CLIENTS).
  • O(n) descriptor scanning on every select() call.

Expected Behavior Under Load:

  • Most memory-efficient.
  • CPU grows faster than pthread at high client counts due to O(n) fd scanning.
  • Hard scalability ceiling at MAX_CLIENTS.

Client Implementation

  • Uses pthread_create() to spawn a dedicated receive thread; the main thread handles sending.
  • Separates sending and receiving logic to allow asynchronous message handling.
  • Terminal-based UI with a command interface.
  • Connects to the discovery server first for authentication, then to the chat server for messaging.

Features

  • User registration and authentication
  • Broadcast messaging
  • Private messaging
  • Active user listing
  • Graceful login and logout handling
  • Performance monitoring and logging

Extra Features

  • Persistent chat history storage
  • User-specific chat history retrieval
  • User state management (active/busy/away)

Protocol Design

Transport Layer

  • TCP is used for reliable, ordered communication.

Message Framing

  • Custom application-layer protocol with a 4-byte big-endian length prefix followed by the message body.
  • Wire format:
[uint32 network-byte-order length][body]
  • The length prefix uses htonl/ntohl to handle endianness correctly across platforms.

Message Format

MessageType|Sender|Receiver|Content

Message Types

Type Description
LOGIN Login request
LOGIN_SUCCESSFUL Successfully logged in
LOGIN_UNSUCCESSFUL Wrong credentials
LOGIN_REPEAT User already logged in
BROADCAST Send message to all users
PRIVATE Send message to one receiver
USER_NOT_ACTIVE Receiver is registered but offline
USER_NOT_FOUND Receiver username does not exist
LOGOUT Signal for logging out
ACTIVE_USERS Request/response for online user list
REGISTER Registration request
REGISTERED Registration successful
REGISTRATION_UNSUCCESSFUL Username already taken
INVALID Invalid instruction
HISTORY Request for a user's chat history
CHANGE_STATE Request to change user state
CHANGE_STATE_FAIL Invalid state provided
UNKNOWN Generic fallback for unexpected errors

Compilation and Execution

Compilation

Build all binaries:

make all

Build individual targets:

make pthread    # client + discovery + server_pthread
make fork       # client + discovery + server_fork
make select     # client + discovery + server_select

Clean build artifacts:

make clean

Running the Discovery Server

Must be started before the chat server and any clients.

./build/discovery

Listens on port 8000.

Running the Chat Server

Start one of the three implementations:

./build/server_pthread   # thread-per-client
./build/server_fork      # process-per-client
./build/server_select    # select()-based non-blocking

All servers listen on port 8080.

Running the Client

./build/client

On startup:

/register <username> <password>   -> register a new account
/login <username> <password>      -> log in to an existing account

Once logged in:

/bc <message>              -> broadcast to all online users
/dm <username> <message>   -> private message to a specific user
/here                      -> list all currently online users
/logout                    -> disconnect gracefully
/help                      -> show command list

Testing Guide

Registration and Login

  1. Start the discovery server and a chat server.
  2. Run ./build/client and register with /register alice pass.
  3. Run a second client and register with /register bob pass.
  4. Verify both clients reach the chat prompt.
  5. Stop and restart both clients, use /login alice pass and /login bob pass to verify credentials persist.

Broadcast Messaging

  1. Connect at least two clients.
  2. From one client, run /bc hello everyone.
  3. Verify the message appears on all other connected clients.
  4. Verify the sender does not receive their own broadcast.

Private Messaging

  1. Connect two clients (alice and bob).
  2. From alice, run /dm bob secret message.
  3. Verify bob receives [Whisper][alice]: secret message.
  4. Verify no other connected clients see the message.
  5. Try /dm nonexistent hi — verify User does not exist!.
  6. Log out bob and try /dm bob hi from alice — verify User is not online right now.

Active User List

  1. Connect three clients.
  2. From any client, run /here.
  3. Verify all three usernames appear.
  4. Log one client out and run /here again — verify the list updates.

Logout and Reconnection

  1. Connect a client and log out with /logout.
  2. Reconnect and log in again — verify no LOGIN_REPEAT error.
  3. Without logging out, kill the client process (Ctrl+C).
  4. Verify the server handles the abrupt disconnect and removes the user from the active list.

Performance Benchmarking

Metrics Collected

Server Metrics:

  • CPU usage (%) — sampled via ps every 5 seconds
  • VmRSS — physical RAM used, shared libraries counted in full (from /proc/<pid>/status)
  • PSS — physical RAM used, shared pages split proportionally (from /proc/<pid>/smaps_rollup); more accurate than VmRSS for fork-based servers since copy-on-write shared pages are divided proportionally across processes

Client Metrics:

  • Message delivery latency — time from send() to arrival in the receiver's buffer, measured using time.perf_counter() in Python

Test Scenarios

Load Test

  • Fixed number of concurrent client pairs (1, 2, 5, 7, 10).
  • Each sender sends 200 private messages to its paired receiver.
  • Resource metrics sampled throughout.

Stress Test

  • Client count progressively increased across runs.
  • CPU, memory, and latency observed as load grows.
  • Bottlenecks identified from degradation points.

Monitoring Module

A separate monitoring thread runs alongside each test. Every 5 seconds it:

  • Reads CPU% via ps -p <pid> -o %cpu
  • Reads VmRSS from /proc/<pid>/status
  • Reads PSS from /proc/<pid>/smaps_rollup
  • For the fork server, sums all metrics across the parent and all child processes
  • Appends one row to output/resource_log.csv

Latency values are written to output/latency_log.csv immediately after each message round-trip is timed.


Visualization and Analysis

Python scripts are used for all plotting. Run the testbench to execute tests and generate plots automatically:

python3 testbench.py

Plots generated in output/:

  • plot1_latency_distribution.png — box plot of latency distribution for each server at each client count
  • plot2_cpu_memory_vs_clients.png — line plots of CPU%, VmRSS, and PSS vs number of client pairs

Performance Analysis Report

See report.pdf.

Covers:

  • Methodology
  • Test results with graphs and data tables
  • Observations and analysis (latency, CPU, VmRSS vs PSS interpretation)
  • Bottlenecks identified
  • Potential optimizations

About

Multi Client chat server implemented using pthread, fork and select for the course CS3205

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages