Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how do you account for when TCP does not get all the bytes in one read

Tags:

c#

.net

tcp

sockets

I just read an article that says TCPClient.Read() may not get all the sent bytes in one read. How do you account for this?

For example, the server can write a string to the tcp stream. The client reads half of the string's bytes, and then reads the other half in another read call.

how do you know when you need to combine the byte arrays received in both calls?

like image 906
Dan Webster Avatar asked Sep 26 '12 06:09

Dan Webster


People also ask

What happens when TCP receive buffer is full?

As the receive buffer becomes full, new data cannot be accepted from the network for this socket and must be dropped, which indicates a congestion event to the transmitting node.

How many bytes can TCP send?

The maximum send buffer size is 1,048,576 bytes. The default value of the SO_SNDBUF option is 32767. For a TCP socket, the maximum length that you can specify is 1 GB.

What is TCP read?

Read TCP Data is an asynchronous activity that reads data from an open TCP connection. The connection must be opened by an activity or a process starter that executed previously in the process.

How does TCP maintain connection?

When two hosts are connected over a network via TCP/IP, TCP Keepalive Packets can be used to determine if the connection is still valid, and terminate it if needed. Most hosts that support TCP also support TCP Keepalive. Each host (or peer) periodically sends a TCP packet to its peer which solicits a response.


1 Answers

how do you know when you need to combine the byte arrays received in both calls?

You need to decide this at the protocol level. There are four common models:

  • Close-on-finish: each side can only send a single "message" per connection. After sending the message, they close the sending side of the socket. The receiving side keeps reading until it reaches the end of the stream.
  • Length-prefixing: Before each message, include the number of bytes in the message. This could be in a fixed-length format (e.g. always 4 bytes) or some compressed format (e.g. 7 bits of size data per byte, top bit set for the final byte of size data). Then there's the message itself. The receiving code will read the size, then read that many bytes.
  • Chunking: Like length-prefixing, but in smaller chunks. Each chunk is length-prefixed, with a final chunk indicating "end of message"
  • End-of-message signal: Keep reading until you see the terminator for the message. This can be a pain if the message has to be able to include arbitrary data, as you'd need to include an escaping mechanism in order to represent the terminator data within the message.

Additionally, less commonly, there are protocols where each message is always a particular size - in which case you just need to keep going until you've read that much data.

In all of these cases, you basically need to loop, reading data into some sort of buffer until you've got enough of it, however you determine that. You should always use the return value of Read to note how many bytes you actually read, and always check whether it's 0, in which case you've reached the end of the stream.

Also note that this doesn't just affect network streams - for anything other than a local MemoryStream (which will always read as much data as you ask for in one go, if it's in the stream at all), you should assume that data may only become available over the course of multiple calls.

like image 133
Jon Skeet Avatar answered Sep 20 '22 22:09

Jon Skeet