A simple client-server key-value store implemented in C using TCP sockets.
The server maintains key-value pairs in memory, and the client provides both interactive and batch modes to manipulate stored data via a custom binary protocol.
- Supports Create, Read, Update, Delete (CRUD) operations
- Keys are integers, values are arbitrary-length byte strings
- Custom binary protocol for reliable transmission over TCP
- Client supports:
- Interactive mode: run commands with a prompt
- Batch mode: execute commands from a file
- In-memory hash-table–based store with persistence across client sessions
- Handles TCP packet-splitting via exact-length
read_n/write_nhelpers - Human-readable error responses
- Single-client server (simple to extend for concurrency)
A fixed 9-byte header followed by an optional value:
- byte 0 : op (ASCII) – 'C' = create, 'R' = read, 'U' = update, 'D' = delete
- bytes 1-4 : int32_t key (network byte order)
- bytes 5-8 : int32_t value_size (network byte order; 0 if no value follows)
- bytes 9.. : value (raw bytes, length = value_size)
A fixed 5-byte header followed by payload:
- byte 0 : status – 'O' (OK) or 'E' (Error)
- bytes 1-4 : int32_t payload_size (network byte order)
- bytes 5.. : payload
- On successful READ: payload = value bytes
- On other successes: payload =
"OK" - On errors: payload = ASCII error message
Compile the server and client using gcc:
gcc -o kv-server kv-server.c
gcc -o kv-client kv-client.c./kv-server <bind-ip> <port>./kv-client interactive./kv-client batch commands.txtconnect <server-ip> <server-port>disconnectcreate <key> <value-size> <value>read <key>update <key> <value-size> <value>delete <key>
- Server stores key-value pairs in a chained hash table
- Memory dynamically allocated for values and freed on deletion
- Server ignores SIGPIPE so broken pipes return errors instead of crashing
- Client enforces active connection before running operations
- Values may be multi-line in batch/interactive mode: if fewer bytes than are provided on one line, the client reads additional input until the full value is collected
- No authentication, no concurrency — can be extended
- Errors returned as ASCII strings for easier debugging