Dial Tone
Before Redis is a database, it's a program listening on a port.
What you're wiring up
A TCP connection is a two-way byte pipe: bytes arrive in arbitrary chunks — not "one message per read" — and your server's whole job is a loop: read some bytes, recognize a command, write some bytes back. This stage builds that loop with exactly one command, PING, and teaches the single most important socket lesson: the network gives you a stream, not messages.
Redis clients speak RESP even for PING, but this stage lets you cheat: you may answer anything that contains PING with +PONG\r\n. Honest parsing is Stage 2's job. We listen on port 6389 — never 6379 — so a real Redis on your machine can't interfere.
# client → server *1\r\n$4\r\nPING\r\n # server → client +PONG\r\n
Assembly steps
hint
net.Listen("tcp", "127.0.0.1:6389") then l.Accept() in a for loop.
hint
Print "listening" to stderr only — stdout stays clean; the harness watches the port, not your logs.
hint
conn.Read returning io.EOF means the client left — close and move on, don't crash.
hint
If your test only gets one PONG back, you probably returned after the first write instead of looping.
hint
Wrap the per-connection loop in a function; call it from the accept loop. Concurrent clients come in Stage 4 — sequential is fine here.
Go deeper (after it passes)
This is the socket layer every server you've ever used sits on. Go deeper: Beej's Guide to Network Programming (free), or just read your own accept loop again — that's nginx's inner shape too.