LUFT is a client-server application for file transfer over UDP, built from scratch on top of the operating system's socket API. The goal is to manually implement the reliability mechanisms that TCP provides natively — segmentation, ordering, error detection, and retransmission — over a protocol that, by nature, offers none of these guarantees.
Reliable file transfer over UDP using raw sockets, without any network abstraction libraries.
- CMake >= 3.25
- Ninja
- GCC with C++23 support
- clang-tidy >= 19 (required — build fails without it)
- zlib
sudo apt install cmake ninja-build g++ clang-tidy-19 zlib1g-devConfigure and compile using one of the available presets:
| Preset | Description |
|---|---|
debug |
All targets, with debug symbols |
release |
All targets, with optimizations |
server-debug |
Server only (debug) |
client-debug |
Client only (debug) |
server-release |
Server only (release) |
client-release |
Client only (release) |
# Configure
cmake --preset debug
# Build
ninja -C build/debugTo build only a specific target (e.g. server or client):
ninja -C build/debug luft_server
ninja -C build/debug luft_clientFor a release build:
cmake --preset release
ninja -C build/releaseBinaries are generated in build/debug/ or build/release/.
The server requires a port and a directory to search files in.
./build/debug/luft_server <port> <search_directory>Example: start the server on port 9000, serving files from /tmp/files:
./build/debug/luft_server 9000 /tmp/filesServer listening on port 9000Errors on startup:
| Situation | Output |
|---|---|
| Wrong number of arguments | Usage: server <port> <search_directory> |
| Directory does not exist | Failed to create server: invalid directory |
| Port already in use | Server error: bind failed |
The client connects to a server and downloads a file.
./build/debug/luft_client <ip> <port> <filename> [output_dir]output_diris optional. If omitted, the file is saved in the current directory.- If a file with the same name already exists, the client automatically renames the new file to
filename (N).ext, incrementingNuntil a free name is found.
Example: download hello.txt from a server running on 127.0.0.1:9000:
./build/debug/luft_client 127.0.0.1 9000 hello.txtExample: download to a specific directory:
./build/debug/luft_client 127.0.0.1 9000 hello.txt /tmp/downloadsErrors:
| Situation | Output |
|---|---|
| Wrong number of arguments | Usage: client <ip> <port> <filename> [output_dir] |
| Output directory does not exist | Failed to create client: invalid output directory |
| Connection or receive failure | Failed to fetch file: receive failed |
| Corrupted packet | Failed to fetch file: deserialize failed |
Open two terminals:
# Terminal 1 — start the server
./build/debug/luft_server 9000 /tmp/files
# Terminal 2 — download a file
./build/debug/luft_client 127.0.0.1 9000 hello.txt