Search code examples
socketstcpposixblocking

send() and write() to TCP output buffer which is full don't block


I am facing a problem with a simple function (language is C++) that iterates over a list of objects, serializes them and send them to a remote server. I am running this function on an ESP32 board that runs FreeRTOS and LwIP, so I have a TCP output buffer which is limited to 5744 bytes by default (I can customize it but I don't want to go over 10-15 thousand bytes).

Basically this is what happen: I call multiple times (in general 200-300 times) a write() or a send() on the socket, each time writing ~1400 bytes. After some time, if the server on the other side is a little bit slow, I saturate the TCP output buffer. Now, from my understanding, the send() or write() should wait until there's some space to write data again to the socket but instead the function immediately returns a value which is different than the value I wanted to write (let's say 1400 bytes).

char buffer[1460];
result = write(current_socket, buffer, 1460);
if(result != 1460){
    // error
} else {
    // everything ok
}

The socket is a default one, so it is a blocking socket and no options have been specified. I'd like the write to block until there's enough space to write all the 1460 bytes specified in the code above. The only reason the write should return an error should be a failure on the other side, for example the server closing the socket. Is this possible?


Solution

  • What you're seeing is called a partial write. This is normal for TCP.

    When the buffer is partly full, a call to write copies as much data as will fit, and returns the number of bytes copied into the buffer. It is your job to deal with the remainder of the data at a later time.

    In order to send your buffer of data, you need to loop until the buffer is empty:

    buf_ptr = 0;
    buf_end = 1460;
    while(buf_ptr < buf_end) {
        rc = write(fd, buf + buf_ptr, buf_end - buf_ptr);
        if(rc <= 0)
            break
        buf_ptr += rc;
    }