Requests, Responses, and Why They Are Not Packets
A message is a run of bytes in a stream
Step 1 of 2 — understand the idea. Read this first and the packet trace will confirm what you already expect, instead of teaching you two things at once.
What you'll be able to do
- ▸Read a request and a response line by line in the raw bytes
- ▸Explain how a receiver knows where a message ends
- ▸Show a case where one message spans packets and one where several share a packet
✗ Common misunderstanding: One packet carries one HTTP request or response.
Why that's wrong: TCP is a byte stream with no message boundaries. It splits by size and coalesces by buffer state, neither of which knows anything about HTTP.
Correct model: A message is a RANGE in a byte stream. Reassemble the stream first, then find messages in it by their framing.
The packets prove it: The persistent-connection trace carries three complete requests in one packet; the large-response trace splits one response across several.
✗ Common misunderstanding: A 404 or a 500 means something is wrong with the network.
Why that's wrong: Both are complete HTTP transactions: the connection worked, the request arrived, and the server answered. The answer was just unwelcome.
Correct model: Any HTTP status at all proves the whole stack beneath it worked. 4xx points at the request, 5xx at the server.
The packets prove it: The server-error trace shows a full handshake, a delivered request, and a 500 — every layer below HTTP demonstrably fine.
Watch these fields in the lab: tcp.payload
- HTTP/1.1
- Text-framed, one request at a time per connection (with pipelining rarely used). What this module teaches, and what you can read in a hex dump.
- HTTP/2
- Same semantics, binary framing, compressed headers, many concurrent streams over one TCP connection. Still TCP, still TLS.
- HTTP/3
- Same semantics over QUIC over UDP. A different stack — no TCP handshake and no separate TLS record layer in the capture.
✗ Common misunderstanding: HTTP is a text protocol.
Why that's wrong: That is true of HTTP/1.1 only. HTTP/2 has been binary-framed since 2015 and HTTP/3 is binary over QUIC, and between them they carry most web traffic.
Correct model: HTTP's *semantics* — methods, status codes, header fields — are shared across versions and defined separately. Only HTTP/1.1's *syntax* is text.
The packets prove it: Every HTTP capture in this module is HTTP/1.1, which is why the request line is legible in the byte view. An HTTP/2 capture of the same request would show HPACK-compressed binary frames.
Watch these fields in the lab: tcp.payload
✓ Concept check — before you open the packets
These test the idea, not the trace. You should be able to answer them from the explanation above.
Now that you understand the concept, observe how it appears in the packet exchange.
The lab runs a real simulated capture — pause, step, click any packet, and inspect every byte.