networking · intermediate · ~15 min · safe pentest lab

Send a message client → server (length-prefixed)

Length-prefixed framing and looped send/recv.

Challenge

TCP is a byte stream with no message boundaries, so to send discrete messages you frame each one with a length prefix. Implement a matching send/receive pair that frames a message as a 4-byte length followed by the payload.

Task

Implement two helpers:

int send_framed(int fd, const char *msg);     /* send one framed message */
int recv_framed(int fd, char *buf, int cap);  /* receive one framed message */

Frame format: a 4-byte length in network byte order (use htonl / ntohl), followed by exactly that many payload bytes (the message length is strlen(msg)).

Input

  • send_framed: a socket fd and a NUL-terminated msg.
  • recv_framed: a socket fd, a destination buffer buf, and its capacity cap.

Output

  • send_framed returns 0 on success, -1 on failure.
  • recv_framed returns the received message length on success, -1 on failure.

Example

send_framed(fd, "hello")        ->   0
recv_framed(fd, buf, cap)       ->   5,  buf="hello"
send_framed(fd, "")             ->   0
recv_framed(fd, buf, cap)       ->   0

Edge cases

  • An empty message frames a length of 0 and round-trips as length 0.

Rules

  • write() and read() may move fewer bytes than requested — loop until all 4 header bytes (and then all payload bytes) have been transferred.

Why this matters

TCP has no message boundaries — frame your messages with a length prefix so the receiver knows where one ends.

Input format

send_framed: a socket fd and a NUL-terminated message. recv_framed: a socket fd, a buffer, and its capacity.

Output format

send_framed returns 0 (success) or -1. recv_framed returns the message length (success) or -1.

Constraints

Frame = 4-byte network-byte-order length + payload. Loop over short write()/read() calls until all bytes move.

Starter code

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int send_framed(int fd, const char *msg) { (void)fd; (void)msg; return -1; }
int recv_framed(int fd, char *buf, int cap) { (void)fd; (void)buf; (void)cap; return -1; }

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.