Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POSIX socket send() function returns before having sent entire buffer

Tags:

c

posix

sockets

Here is what the code roughly looks like:

int main() {
    // All the details needed before using the send() function here...

    send(socket, buffer, 1024*1024*1024, 0);
    return 1;
}

If send() is supposed to be blocking regardless of the size of the buffer then I think it shouldn't return until the entire buffer has been sent. But from what I have observed, given a large enough buffer, it does return before send() has sent the entire buffer.

However, if I add this code before the return statement:

while(1){}

send() blocks as expected and sent the entire data.

Isn't send() supposed to be blocking like that or is there something wrong with the send() function itself?

Thanks in advance.

like image 941
Courage Avatar asked Jul 18 '26 11:07

Courage


1 Answers

When blocking socket is used, send() function blocks until last data is delivered to queue of local TCP-stack.

So send() may return when part of the data is still queued in local TCP-stack. Because your process exits right after send() call, there can be undelivered data in local TCP stack during exit.

TCP stack may continue the data transfer after exit, if linger is enabled. Or TCP stack may reset the connection without any attempt to transfer undelivered data to the peer, if linger is disabled.

If you close the TCP connection gracefully when linger is enabled, then TCP-stack should (try to) deliver queued data to the peer.

Close the connection gracefully by adding close() call. And make sure that SO_LINGER is enabled with reasonable timeout:

send(socket,buffer, 1024*1024*1024,0);

const struct linger linger_val = { 1, 600 };
setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_val, sizeof(linger_val));

close(socket);
return 1;

Usually there is no need to change SO_LINGER. More information about SO_LINGER in man page of socket(7):

SO_LINGER
              When enabled, a close(2) or shutdown(2) will not return until
              all queued messages for the socket have been successfully sent
              or the linger timeout has been reached.  Otherwise, the call
              returns immediately and the closing is done in the background.
              When the socket is closed as part of exit(2), it always
              lingers in the background.
like image 161
SKi Avatar answered Jul 21 '26 01:07

SKi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!