2

It is my understanding that a write to a TCP/IP socket will be atomic if the amount of data written is small. By atomic, I mean that the receiver will receive all of the data or none of the data. However, it is not atomic, if the amount of the data written is large. Am I correct? and if so, what counts as large?

Thanks, Bob

Bob
  • 290
  • 3
  • 12
  • 1
    Bob, your question is good and many programmers have the error that they think that if they send N Bytes in a TCP socket, the other node will read all N Bytes. Then, they run functional test and works. However, that's a bug that will generate a failure in the system at some moment. What you want to do is create a simple application layer protocol, usually TLV (Type, Length, Value). I explain it here (the problem is valid for any programming language): http://stackoverflow.com/questions/19839172/how-to-read-all-of-inputstream-in-server-socket-java/19863726#19863726 – rodolk Apr 14 '17 at 16:59

2 Answers2

3

No. TCP is a byte-stream protocol. No messages, no datagram-like behaviour.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Based upon the responses I have received, if the server writes a four byte integer and the client reads a four byte integer, the read might only return two bytes because the write is not atomic and a subsequent read will then return the other two bytes. Do I have that right? Bob. – Bob Apr 14 '17 at 12:37
1

For UDP, that is true, because all data written by the app is sent out in one UDP datagram.

For TCP, that is not true, unless the application sends only 1 byte of data at a time. A write to a TCP socket will write all of the data to a buffer that is associated with that socket. TCP will then read data from that buffer in the background and send it to the receiver. How much data TCP actually sends in one TCP segment depends on variables of its flow control mechanisms, and other factors, including:

  • Receive Window published by the other node (receiver)
  • Amount of data sent in previous segments in flight that are not acknowledged yet
  • Slow start and congestion avoidance algorithm state
  • Negotiated maximum segment size (MSS)

In TCP, you can never assume what the application writes to a socket is actually received in one read by the receiver. Data in the socket's buffer can be sent to the receiver in one or many TCP segments. At any moment when data is made available, the receiver can perform a socket read and return with whatever data is actually available at that moment.

Of course, all sent data will eventually reach the receiver, if there is no failure in the middle preventing that, and if the receiver does not close the connection or stop reading before the data arrives.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
rodolk
  • 5,606
  • 3
  • 28
  • 34
  • 3
    "*unless the application sends only 1 byte of data at a time*" - even that is not a guarantee, since the data is buffered by default. You could perform multiple 1-byte writes and still have them sent out together in a single TCP segment, unless you enable the `TCP_NODELAY` socket option. – Remy Lebeau Apr 14 '17 at 00:33
  • 1
    And in any case you could still *receive* them all in a single receive operation. @RemyLebeau – user207421 Apr 14 '17 at 00:48
  • @EJP: yes, if multiple TCP segments are received and buffered in the socket before the app performs a new read operation. – Remy Lebeau Apr 14 '17 at 00:57
  • 1
    @RemyLebeau and EJP, that is correct! Many 1 Byte writes may be sent in only one segment. And the receive application might read them in one or multiple read operations. Thank you for the clarification. – rodolk Apr 14 '17 at 16:50