a simple echo client and server
Every craft has its first simple project that uses every basic tool once - in networking it is the echo server. The server's whole job is to listen for a client, read whatever bytes the client sends, and send those same bytes straight back. The client connects, sends a line, and prints what comes back. If your echo pair works, you have correctly exercised the entire socket API once, which is why it is the 'hello world' of network programming.
Putting the pieces together: the server calls socket(), bind() to a port, listen(), then loops calling accept() to get a connected socket per client; for each client it loops recv() to read bytes and send() to write the same bytes back, until recv() returns 0 (the client closed), then close()s that connected socket. The client calls socket(), connect() to the server's address (often 127.0.0.1 on a chosen port), then send()s some data and recv()s the reply, looping if the reply arrives in pieces. Crucially, even this tiny program must loop on send() and recv() rather than assume one call moves everything, because TCP is a byte stream with no message boundaries - the echo server simply relaying whatever it gets sidesteps framing, which is part of why it is the natural first example.
Why it matters: the echo pair is the smallest complete artifact that touches socket(), bind(), listen(), accept(), connect(), send(), recv(), and close() together, plus byte-order conversion for the port and the recv()-returns-0 close signal. Build it once, get it running over loopback, and the abstract calls become concrete. From here, a chat server, a web server, or any protocol is the same skeleton with richer rules layered on top - which is exactly what later fields and Volume II explore.
Server inner loop: for (;;) { ssize_t n = recv(c, buf, sizeof buf, 0); if (n <= 0) break; /* 0 = client closed, <0 = error */ size_t off = 0; while (off < (size_t)n) { ssize_t m = send(c, buf + off, n - off, 0); if (m < 0) break; off += m; } } It reads a chunk and sends it all back, looping send() to handle partial writes.
The whole echo server: recv a chunk, loop send() until it is all returned, repeat until the client closes.
An echo server hides framing because it never needs to know where one message ends - it relays raw bytes. The moment you build a real protocol you must add framing yourself; do not let the echo example fool you into thinking TCP delivers messages.