Master the fundamental concepts of inter-process communication through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksUnix domain sockets (AF_UNIX) move bytes between processes on one machine with stream or datagram semantics. Paths bind to filesystem names; SCM_RIGHTS can pass file descriptors.
Server steps:
socket(AF_UNIX, SOCK_STREAM, 0)bind to path, listen, acceptread/write on connected fdFor example, /tmp/app.sock may carry RPC requests while TCP stack stays untouched, lowering latency for local services.
AF_UNIX sockets are exactly how the Docker daemon exposes its API at /var/run/docker.sock, how X11 clients talk to the display server, and how systemd's D-Bus implementation passes messages locally, all chosen specifically because filesystem permissions on the socket path double as an access-control mechanism. The SCM_RIGHTS file-descriptor-passing feature mentioned here is a real production technique: privilege-separated daemons like OpenSSH use it to hand a already-opened, permission-checked fd to an unprivileged worker process.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will implement echo server and client with stream sockets and cleanup the bound path on exit. This exercise requires handling EADDRINUSE when stale socket files remain.
Build a tiny key-value server and its client that talk over a Unix-domain stream socket, the local IPC that Docker, systemd and X11 use. The program forks. The child is the server: it reads newline-terminated requests from its end of the socket and writes one reply line per request. The parent is the client: it sends each input line as a request, reads the reply, and prints both. A stream socket has no message boundaries, so both sides must frame messages themselves (here, with newlines) and cope with partial reads.
Create a connected pair with socketpair(AF_UNIX, SOCK_STREAM, 0, sv), or bind/listen/accept on a socket file under /tmp (unlink it afterwards). The output is the same either way.
| Request | Reply |
|---|---|
SET KEY VALUE... | OK (the value is the rest of the line; setting an existing key replaces it) |
GET KEY | VALUE ... or NOTFOUND |
DEL KEY | DELETED or NOTFOUND |
COUNT | N (number of keys) |
QUIT | BYE, then the server closes its socket and exits |
| anything else | ERR unknown command |
When the server exits: after QUIT, or when it reads end-of-file because the client closed its sending side: its exit status is the number of keys it holds (at most 255).
For each input line, print > LINE and send it, then print < REPLY once the reply arrives. Blank lines are skipped. After QUIT, send nothing more; any remaining input lines print > LINE then < (server gone). At the end of the input, if the server is still running, call shutdown(fd, SHUT_WR) so the server sees end-of-file. Finally waitpid and print server exited with status N.
Input:
cLoading…
Output:
cLoading…
read() into a buffer and split on \n, because one read may return half a line or several lines.SIGPIPE (or uses MSG_NOSIGNAL) so that writing to a closed socket returns an error instead of killing it.Hidden tests cover overwriting a key, values containing spaces, GET/DEL of missing keys, an unknown command, and QUIT in the middle of the input with more lines after it.