ThinkAloud
Projects
ThinkAloud
  1. 01Projects21 ready to build and explain
Browse projects
Theme

Projects from Coding Challenges by John Crickett

Projects/Echo Server

Build your own echo server

A server that sends back every byte a client sends it, first over TCP and then over UDP, following the one-page Echo Protocol in RFC 862. Building it teaches what sits under every network service: how a connection is accepted and how its end shows up, why TCP delivers a stream of bytes rather than messages, how one program serves many clients at once, and how it stops without losing data.

From Coding Challenges #100 ↗ by John Crickett

  • Challenge #100
  • Beginner
  • 6 concepts
  • 6 steps
  • Not yet checked
Start Echo Server

No sign-up. You tell the mentor your language: Java, Python or Node.js.

What you'll learn · 6 concepts

The concepts behind Echo Server

In the order the steps use them. Each one links to the best places to learn it, and you explain it in your own words once its steps are built.

  1. 1Sockets and the life of a connectionStep 2, 4

    Step 1 binds, listens and accepts one client by hand, and step 3 has to notice the moment that client goes away.

    Covers: bind, listen and accept · the listening socket versus connected sockets · the queue of connections waiting to be accepted · wildcard and loopback addresses · privileged ports · the client's temporary port · a read of zero bytes means the peer closed

    Beej's Guide to Network Programming ↗ · listen(2), Linux manual page ↗ · recv(2), Linux manual page (see the return value) ↗

  2. 2TCP is a byte stream, not a series of messagesStep 4

    Step 3 reads from a connection and writes the same bytes back, and it only works if those bytes are treated as a stream rather than as lines or messages.

    Covers: no message boundaries · one write can arrive in several reads, and several writes in one · echo only the bytes each read returned · a write can take fewer bytes than it was given · bytes, not text · flow control and full buffers

    RFC 9293: Transmission Control Protocol (TCP) ↗ · Message Framing (Stephen Cleary) ↗

  3. 3Serving many clients: threads, event loops and their costsStep 3

    Step 2 has to keep accepting new clients while earlier ones stay connected, which a single loop that waits on one client can't do.

    Covers: why one loop can serve only one client · a thread or task per connection · an event loop over many sockets · memory and switching costs · slow and idle clients · state shared between connections

    Concurrent Servers, Part 1: Introduction (Eli Bendersky) ↗ · Concurrent Servers, Part 3: Event-driven (Eli Bendersky) ↗ · The C10K problem (Dan Kegel) ↗

  4. 4Streams versus datagrams: TCP and UDPStep 5

    Step 4 runs the same service over UDP, where the server never sees a connection, only datagrams that each carry a return address.

    Covers: connections versus independent datagrams · one socket for every client · replying to each sender's address · boundaries kept, delivery not promised · datagrams cut short by a small buffer · forged senders

    RFC 768: User Datagram Protocol ↗ · RFC 8085: UDP Usage Guidelines ↗ · udp(7), Linux manual page ↗

  5. 5Graceful shutdown and drainingStep 6

    Step 5 asks the server to close every connection and send back any echoes still in flight before it exits.

    Covers: stop signals, and the one that can't be caught · stop accepting first · draining data already received · closing the write side to signal the end · waking handlers that are blocked · a deadline for clients that never leave

    shutdown(2), Linux manual page ↗ · The ultimate SO_LINGER page, or: why is my TCP not reliable (Bert Hubert) ↗ · Pod Lifecycle, see Termination of Pods (Kubernetes documentation) ↗

  6. 6Reading an RFC and turning it into behaviourStep 4

    Step 3 is where the RFC's single rule for TCP, send back whatever arrives until the client ends the connection, becomes exact behaviour, with nothing added and nothing left out.

    Covers: what kind of RFC it is, and whether it is current · requirement words, and RFCs older than them · one statement, one testable rule · what the spec leaves open

    RFC 862: Echo Protocol ↗ · How to Read an RFC (Mark Nottingham) ↗ · RFC 2119: Key words for use in RFCs to Indicate Requirement Levels ↗

What you'll build · 6 steps

Build Echo Server step by step

Steps of 30 to 60 minutes, in your own editor and language. Each one has a check, so you know when it works.

  1. 01

    Set up

    Create the project, read RFC 862, and make sure netcat or telnet is installed to act as a client. The server listens on the port named in the PORT environment variable rather than the privileged port 7, so it runs and can be tested without special rights.

    Works whenYou can say in a sentence what the RFC asks of the TCP service and of the UDP service, and nc can open a connection to a port on your machine.

  2. 02

    Accept one connection

    Bind to all local addresses on the port from PORT, listen, accept a single TCP connection, log the client's address and port, and then exit.

    Works whenWith the server running, connecting with nc to that port on localhost makes the server log the connection with the client's address, such as 127.0.0.1, and a client port that changes on every run, and then exit.

    Concepts: sockets and the life of a connection

  3. 03

    Serve many clients at once

    Keep accepting after the first client. The main loop goes back to listening while each client is handled by its own concurrent unit of work, a thread or an async task.

    Works whenSeveral nc clients connected at the same time are each logged with a different client port, and the server keeps running when any of them leaves.

    Concepts: serving many clients

  4. 04

    Echo the data

    Read whatever each client sends and write the same bytes back, until the client disconnects. Then log that the client disconnected and carry on serving the others.

    Works whenA line typed into nc comes back unchanged, two clients connected together each get back only their own data, and closing a client logs the disconnection while the server keeps running.

    Concepts: TCP is a byte stream, not a series of messages · sockets and the life of a connection · reading an RFC and turning it into behaviour

  5. 05

    Echo over UDP

    Add a -udp flag that runs the service over UDP on the same port. Each datagram received is sent back unchanged, in a datagram addressed to its sender. Log that the server is listening for UDP.

    Works whenUsing nc in UDP mode with -u, a line typed and sent to the port comes back unchanged.

    Concepts: streams versus datagrams

  6. 06

    Shut down cleanly

    When asked to stop, stop accepting new clients, finish sending back everything already received, close every connection, and exit.

    Works whenThe page gives no test. One way: with clients connected and data on its way, stop the server. Every byte it had already received still comes back, the clients see the connection close cleanly rather than reset, and the process exits promptly with a success code.

    Concepts: graceful shutdown and draining

Ready to start Echo Server?

Start Echo Server

From Coding Challenges #100 ↗ by John Crickett. Notes written in our own words.

Projects from Coding Challenges by John Crickett