TCP and UDP/TCP, step by step/TCP is a byte stream
Lesson 6 of 12 · in 3D and VR

TCP is a byte stream

TCP gives an application an ordered stream of bytes. The segments it cuts that stream into are its own business, and they are not the application's messages.

Lonely BinaryUpdated 2026-10-014 min readNo board required

View it in VR

Lesson 6 of the TCP and UDP course opens in a VR headset, on a table in front of you, and a voice starts three seconds after you arrive. Type this short address into the browser on a headset such as Meta Quest or Apple Vision Pro, and press Enter VR. No headset? Press Start the lesson: the same lesson, full screen.

learn.lonelybinary.com/vr/tcp-udp/6

An application writes to TCP in calls: forty bytes now, two hundred a moment later. TCP does not keep those calls. It appends the bytes to one stream, numbers every byte, and decides on its own how to cut the stream into segments. RFC 9293 calls the service a reliable, in-order byte stream.

Three sets of boundaries

There are three, and they do not have to agree. The application's writes are where each call ended. TCP's segments are where it cut the stream, mostly by size: on an Ethernet link, with IPv4 and no options, a segment carries up to 1460 bytes of data. On an ESP32 the limit is a little lower, about 1440, and it is set when the firmware is built. The application's reads are however much each call asked for and found waiting.

RFC 9293 says it plainly: TCP guarantees no correlation between the boundaries of the segments sent and received, and the boundaries of the read and write buffers of the application.

What comes out

Two writes can come out as one read, because both had arrived before the program asked. One write can come out as two reads, because it was cut in two, or because the program only asked for part of it. A message that fitted in one segment today can arrive in two tomorrow, when the path is different.

Nothing is lost in all this. The bytes are all there, in the order they were written, and TCP holds back any that arrive too early so that the program never sees them out of order. What is gone is only the marks between writes.

Marking the ends yourself

If the data is made of messages, the messages carry their own ends. Two ways are common:

  • A length first. Send a number that says how many bytes follow, then read exactly that many, however many reads it takes.
  • A terminator. End each message with a newline, and read until one turns up. This works only if the newline cannot appear inside a message.

HTTP uses both ideas: a header ends with a blank line, and the body is as long as Content-Length says (or is sent in marked chunks).

Common mistakes

  • Reading once and treating the result as one message. It may be half of one, or one and a half.
  • Assuming a short write is a short segment. TCP may hold small writes back and send them together, or send them at once.
  • Parsing before the newline has arrived. Keep what you have read, and wait for the rest.
  • Sizing a buffer to the write. Size it to the largest message the protocol allows.

Edit this page — content/fundamentals/tcp-udp/tcp-byte-stream.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Fundamentals on the forum →