A small TCP chat server (42 mini_serv-style) implemented in C.
It accepts multiple clients on 127.0.0.1:<port>, assigns each a numeric id, and broadcasts:
- arrivals:
server: client <id> just arrived\n - departures:
server: client <id> just left\n - messages (line-based):
client <id>: <line>\nto all other clients
Messages are delimited by \n. If a client sends multiple lines, each line is broadcast separately with the prefix.
Partial TCP frames are handled by buffering until a newline is received.
Note:
serv.cin this repo is a “clean/testing-friendly” version and uses a few exam-forbidden functions (notablysignal()and C11 atomics) so you can stop the server withCtrl+Cwithout leaking sockets during testing.
serv.c— the server implementationmakefile— build rules (+ helpers for Docker)dockerfile— Debian image withcc,valgrind,netcatandbuntester/tester.ts— Bun-based functional + stress tester
makeThis produces ./serv.
The server expects a single argument: the port.
./serv 8080The server binds to 127.0.0.1 only.
In separate terminals:
nc 127.0.0.1 8080Type lines and press Enter. Other connected clients will receive your messages prefixed as
client <id>: ....
The tester targets 127.0.0.1:8080 by default.
- Start the server:
./serv 8080- In another terminal, run the tester from the
tester/folder:
bun tester.tsWhat it checks (high-level):
- arrival/departure broadcasts
- sender does not receive its own messages
- line-by-line prefixing for multi-line sends
- TCP fragmentation handling (split writes)
- stress: connects ~1000 clients (bounded concurrency) and sends a ~100kB line in <=800B chunks
The provided dockerfile creates a Debian image with build tools, valgrind, nc, and bun.
Build the image:
make docker_buildRun an interactive shell inside the container:
make docker_runRun a second shell inside the container:
make docker_attachInside the container:
make
./serv 8080Then (in another container shell, or background the server), you can run:
cd tester
bun tester.ts- Line buffering: each client accumulates bytes until
\n, then broadcasts that line. - Message size: there is a large fixed buffer (
MAX_MESSAGE_LENGTH) used for assembling a line. Extremely long lines without newlines can overflow if they exceed this limit. - The server uses
select()andfd_sets and stores per-client state indexed by file descriptor. - Broadcast uses
send(..., MSG_NOSIGNAL)to avoidSIGPIPEwhen writing to closed sockets.
- Tester says it can’t connect: ensure the server is running on port
8080and bound to127.0.0.1. - Port already in use: stop any existing server or pick another port (and update
tester/tester.tsif needed). - Docker make target typo: the Makefile includes
docker_build; running containers is done with thedocker run ...command shown above.