Write a TCP Client for a Chat Server
A TCP connection is a symmetric, bidirectional byte stream - and it has no idea where one "application message" ends and the next begins. That becomes a problem the moment you want to design a communication protocol on top of it, and a simple chat server illustrates it very well.
The application has to impose its own structure on the raw byte stream sent over a TCP connection,
and one of the simplest ways to do that is to delimit messages with a newline (\n).
In the telemetry client challenge
you only had to connect() and read a one-way push stream. This time, you'll go a
step further and hold a real back-and-forth conversation with a server.

Berkeley Sockets API cheat sheet.
The Task
A chat server is running on a separate host at 172.16.0.10:5000. It speaks
a simple line-based protocol:
- The server reads one line at a time - everything up to and including a
\nis one message. - For every message you send, it answers with one line of gibberish, like:
wibble zonk frobnicate quux sig=9f3a1c0b7e2d4a85
The content of the lines you send doesn't matter (hello\n is perfectly
fine) - what matters is that each one is a complete, newline-terminated message.
Your task is to write a client that holds a short conversation with the server:
- Connect to
172.16.0.10:5000from thedev-01machine. - Send at least 3 messages, reading the server's reply after each one.
- Save the server's replies into
~/chat.logso they can be verified.
You can use any language to write your client. The playground already has gcc (for C/C++), Python, Node.js, and Go installed. If you prefer a different stack, install it yourself.
Hint 1: The conversation loop
After connect()-ing, the client needs to:
- Read a single line from the user.
- Send it to the server (ensuring it ends with a
\n). - Read a full line back from the server.
- Print that reply so it can be copied into the transcript at
~/chat.log.
The client section of the How Servers Work tutorial
shows the basic connect() / send() / recv() skeleton you can build this on.
Hint 2: Framing what you send
The server won't react until it sees a \n - that's how it knows one message has ended.
So every line you send must be terminated with a newline. If you send() "hello" without the \n,
the server keeps waiting for the rest of the line and never replies, and your client blocks
forever on the next read.
Hint 3: Framing what you receive
TCP doesn't preserve message boundaries, so a single recv() may hand you only
part of a line - the server's reply can be split across several reads.
Don't assume one recv() returns one whole message.
Work with the raw recv() calls and reassemble lines yourself: keep an incoming buffer,
append whatever each read returns, and keep reading until the buffer holds a complete
line (everything up to the \n). Then split that line off and keep any leftover bytes
in the buffer for next time.
That little buffer is the whole trick to reading a line-oriented protocol off a byte stream.
Hint 4: Capturing the transcript with tee
The verifier looks for the server's replies in ~/chat.log. Instead of
writing the file from your client, just print every line you receive from the
server to stdout and let the shell capture it with
tee:
./chat_client | tee ~/chat.log
That keeps your client code focused on the conversation while the transcript lands in the file for the check.