Error detection and correction
Before we move on, I do want to take a brief moment to talk about the distinction between error detection and error correction. You might have wondered why I left out any stipulation regarding error correction or error detection from my definition of a packet. This is because there is no guarantee that, for every protocol defined for the transport layer of the OSI stack, packets will always contain sufficient information to detect or correct errors incurred in transit.
I will say, however, that it is extremely common to have at least some kind of error detection in a given protocol specification. TCP, and even the unreliable UDP transport protocol, provide a checksum for simple error detection, as seen in the following two packets on Wireshark:
What those protocols don't provide, however, is any mechanism for error correction, which is actually much more difficult to implement, and for anything other than trivial correction capabilities, will require the packet size to balloon upwards. For example, while a checksum can tell you whether the payload has altered in transit somehow, it cannot tell you specifically where, or to what extent, the payload may have been altered. To do so would require enough additional data to reconstruct the packet from scratch. Since packet transmission is generally reliable over time (which is to say, even if one transmission failed, retrying the transmission is likely to succeed), and generally exceptionally fast at the transport layer, it's always a much better idea to simply detect an error, discard the erroneous packet, and request retransmission.
With this in place, we have a solid idea of everything that a packet defined under a given protocol must have, and of how we can examine or use individual pieces of network data. But our software won't be using tiny little pieces of individual data. Our software will be expecting JSON objects, XML payloads, or serialized byte-streams of C# objects. So, how does software that consumes network traffic make heads or tails of those random flows of bite-sized packets? By using them as streams.