Challenge, Medium,  on  NetworkingProgrammingLinux

Make One Echo Server Work with Both TCP and Unix Sockets

In the Write a TCP Echo Server From Scratch challenge, you built a server that accepts a connection, reads whatever bytes the client sends, and writes those exact same bytes back. That server listened on a TCP socket - an AF_INET address like 127.0.0.1:4000.

But SOCK_STREAM is not exclusive to TCP. The very same listen()/accept()/recv()/send() workflow also works with a Unix domain socket (AF_UNIX) in the stream mode (SOCK_STREAM) - a local socket addressed by a filesystem path and reachable only from the same host.

Berkeley Sockets API Cheat Sheet.

Berkeley Sockets API Cheat Sheet.

In this challenge, you'll make one echo server speak over both kinds of connection-oriented stream sockets, chosen at startup by a single command-line argument.

Your task is to write an echo server that takes the listen address as its only command-line argument and:

  1. If the argument looks like unix:///path/to/file, the server creates a Unix domain stream socket and listens on that path.
  2. If the argument looks like <host>:<port>, the server creates an IPv4 TCP socket and listens on that host and port.
  3. Echoes back every byte it receives from a client, exactly as in the original challenge.

To pass the verification, launch your server twice - two instances of the very same program:

./server 127.0.0.1:4000
./server unix:///tmp/echo.sock

The checker connects to both endpoints and verifies that each one echoes correctly.

You're free to use any language to implement the server. The playground already has gcc (for C/C++), Python, and Go installed. Prefer a different stack? You will need to install it yourself.

Hint 1: One program, two address families

The accept loop, the read-until-EOF logic, and the echo-back logic are identical for both stream sockets. The main difference is how you create and bind the listening socket:

  • For <host>:<port>, create an (AF_INET, SOCK_STREAM) socket and bind it to that host and port - exactly what you did in the original echo server challenge.
  • For unix:///path, create an (AF_UNIX, SOCK_STREAM) socket and bind it to the filesystem path (the part after unix://).

Parse the single argument first, decide which kind of listening socket to make, and then fall through into the same connection-handling loop.

Hint 2: Unbinding a stale Unix socket

A pathname-based Unix domain socket leaves a socket file behind at its bind path. If that file already exists when you bind(), the call fails with EADDRINUSE ("Address already in use"). Remove a leftover socket file (e.g. with unlink()/os.unlink/os.Remove) before binding. Many languages' higher-level helpers won't do this for you, so it's a common first issue.

If you're reusing the address-creation steps from the How Servers Work: A Hands-On Introduction to TCP Sockets tutorial, note that everything after bind() can stay the same.