Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 

Repository files navigation

TCP Chat Server & GUI Client

Final project for Advanced Programming course at Columbia University.

Overview

This project is a multi-client chat application written in C using IPv4 TCP sockets and POSIX APIs. A central server accepts concurrent connections and broadcasts each user's messages to the other connected clients. The client combines framed network communication with an ncurses interface for message entry, history, scrolling, status updates, and terminal resizing.

The repository pairs a completed networking client with the reference server and shared protocol utilities supplied for the course. This makes the full client/server protocol runnable locally while keeping the implementation boundary explicit.

Architecture

flowchart LR
    A[GUI Client A] -->|framed TCP messages| S[TCP Chat Server]
    B[GUI Client B] -->|framed TCP messages| S
    C[GUI Client C] -->|framed TCP messages| S
    S -->|broadcast| A
    S -->|broadcast| B
    S -->|broadcast| C
Loading

The server uses select() to watch its listening socket and active client sockets. It accepts up to three simultaneous clients, associates each connection with a username, and broadcasts chat and presence messages. The client connects to a validated IPv4 address and port, receives a welcome message, sends its username, and then enters an event loop.

Client Event Loop

The client rebuilds an fd_set on every iteration and uses select() with a short timeout to monitor both STDIN_FILENO and the connected socket.

flowchart TD
    L[Client event loop] --> S[select on STDIN and socket]
    S -->|STDIN ready| I[Read GUI keystroke or redirected line]
    I --> M[Frame and send message]
    S -->|Socket ready| R[Receive one framed message]
    R --> U[Update status and GUI history]
    S -->|Timeout or signal interruption| L
    M --> L
    U --> L
Loading

This keeps terminal input and incoming network traffic responsive without dedicating a thread to either source.

Technical Implementation

  • Creates IPv4 TCP sockets with socket() and establishes client connections with connect().
  • Validates dot-decimal IPv4 addresses with inet_pton() and checks command-line port and username constraints.
  • Frames every message with a 16-bit network-byte-order length through send_with_length() and recv_with_length().
  • Multiplexes standard input and the client socket using select(), fd_set, FD_SET, and FD_ISSET.
  • Supports interactive ncurses input as well as newline-delimited input redirected from a file.
  • Integrates asynchronous messages into a fixed-capacity circular history queue used by the GUI.
  • Tracks normal departure, server shutdown, connection loss, and select() failure as explicit client states.
  • Uses sigaction() for server SIGINT shutdown and ignores SIGPIPE in the client; the GUI also contains handlers for SIGINT and SIGWINCH, with a registration gap noted below.
  • Reports system-call failures with errno and strerror() and releases sockets, allocated usernames, queue entries, and ncurses windows during normal cleanup paths.
  • Uses SO_REUSEADDR on the server and rejects connections beyond its configured capacity.

Key Engineering Challenges

  • Preserving message boundaries over TCP, which exposes a byte stream rather than message-sized records.
  • Responding to user input and network events concurrently without a threaded client.
  • Detecting orderly shutdowns and unexpected peer disconnects from socket return values.
  • Keeping message history and screen state consistent while messages arrive asynchronously or the terminal is resized.
  • Integrating networking and lifecycle logic into an existing GUI-oriented C codebase.
  • Managing file descriptors and heap-backed message data across connection and shutdown paths.

What I Implemented

Repository history and the retained completion markers show that the project work focused on the client-side networking integration: argument validation, socket creation and connection setup, the welcome/username handshake, framed send/receive handling, select()-based input multiplexing, GUI message dispatch, redirected-input support, shutdown-state handling, welcome-message parsing, queue lifecycle calls, and the Makefile targets.

The ncurses GUI framework, circular queue implementation, shared protocol helpers in util.h, and chat server were provided as course infrastructure. The work involved completing and extending that supplied client skeleton rather than authoring every function from scratch.

Build

The client requires a C compiler, Make, and ncurses development headers. On Debian or Ubuntu, the ncurses dependency can be installed with:

sudo apt install libncurses-dev

Build both executables from the source directory:

cd src
make

To remove generated binaries and object files:

make clean

Running

Start the server with an available port in the supported range:

cd src
./chatserver 43127

Then launch one or more clients in separate terminals:

cd src
./chatclientgui 127.0.0.1 43127 alice

Use a distinct username for each client. Messages sent by one client are relayed to the other connected clients.

Redirected standard input is also accepted:

./chatclientgui 127.0.0.1 43127 alice < messages.txt

See Known Limitations before relying on redirected-input shutdown behavior.

Example Architecture

Client A ─┐
Client B ─┼→ TCP Server → Message broadcast
Client C ─┘

Tech Stack

  • C
  • POSIX sockets and signals
  • TCP/IP
  • select()-based I/O multiplexing
  • ncurses
  • Make

Known Limitations

  • The client defines SIGINT and SIGWINCH handling but does not currently register those handlers, so those signal-driven client paths are incomplete.
  • After redirected standard input reaches bye or end-of-file, the non-GUI client can remain in its event loop instead of terminating.
  • The supplied framing helpers assume each send() or recv() transfers the complete requested buffer; production code should loop to handle partial TCP I/O.

What I Learned

This project developed practical experience with TCP connection setup, file-descriptor lifecycle, length-prefixed protocols, and multiplexed I/O. It also required tracing state across signals, terminal events, socket disconnects, and an existing ncurses codebase—the same kinds of boundaries that make client/server debugging substantially different from debugging a standalone program.

About

Final project for Advanced Programming Course at Columbia University

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages