Receiving data from already closed socket?
Asked Answered
S

3

7

Suppose I have a server application - the connection is over TCP, using UNIX sockets.

The connection is asynchronous - in other words, clients' and servers' sockets are non-blocking.

Suppose the following situation: in some conditions, the server may decide to send some data to a connected client and immediately close the connection: using shutdown with SHUT_RDWR.

So, my question is - is it guaranteed, that when the client call recv, it will receive the (sent by the server) data?

Or, to receive the data, recv must be called before the server's shutdown? If so, what should I do (or, to be more precise, how should I do this), to make sure, that the data is received by the client?

Seraglio answered 9/8, 2012 at 18:34 Comment(0)
Q
5

You can control this behavior with "setsockopt(SO_LINGER)":

SO_LINGER Waits to complete the close function if data is present. When this option is enabled and there is unsent data present when the close function is called, the calling application is blocked during the close function until the data is transmitted or the connection has timed out. The close function returns without blocking the caller. This option has meaning only for stream sockets.

See also:

Queston answered 9/8, 2012 at 18:38 Comment(7)
Right, the answer is it depends on what socket options the server set.Polston
How exactly does this answer the question? He didn't ask how to control the behaviour at the sender, he asked what is the behaviour at the receiver. Setting a linger timeout doesn't alter that in the slightest. (Turning it off does, but you haven't mentioned that.)Ursas
I don't get it. So, I need to set SO_LINGER, and then the close function will not close the socket before the client receive the data or a timeout occurs, right? If so, then how "The close function returns without blocking the caller"? Or, maybe, the OS will take care of this and my server will NOT block on close? Also, +1 for @EJP's comment.Seraglio
Also, the Beej's guide says nothing about this. I've read it, I just looked at it again and I didn't see anything about this case.Seraglio
this does not answer the questionBost
@Polston It doesn't depend on any such thing. All that SO_LINGER does is control the close timeout at the sender. It doesn't change the behaviour at the receiver in the slightest.Ursas
@EJP: The asker presumably only has control of the server. The server presumably wants to close the connection after it sends the data. If the server enables linger with 0 timeout, the client will likely lose data. Upvoting your correct answer.Polston
U
5

There's no guarantee you will receive any data, let alone this data, but the data pending when the socket is closed is subject to the same guarantees as all the other data: if it arrives it will arrive in order and undamaged and subject to TCP's best efforts.

NB 'Asynchronous' and 'non-blocking' are two different things, not two terms for the same thing.

Ursas answered 9/8, 2012 at 22:26 Comment(0)
A
4

Once you have successfully written the data to the socket, it is in the kernel's buffer, where it will stay until it has been sent and acknowledged. Shutdown doesn't cause the buffered data to get lost. Closing the socket doesn't cause the buffered data to get lost. Not even the death of the sending process would cause the buffered data to get lost.

You can observe the size of the buffer with netstat. The SendQ column is how much data the kernel still wants to transmit.

After the client has acknowledged everything, the port disappears from the server. This may happen before the client has read the data, in which case it will be in RecvQ on the client. Basically you have nothing to worry about. After a successful write to a TCP socket, every component is trying as hard as it can to make sure that your data gets to the destination unharmed regardless of what happens to the sending socket and/or process.

Well, maybe one thing to worry about: If the client tries to send anything after the server has done its shutdown, it could get a SIGPIPE and die before it has read all the available data from the socket.

Alainaalaine answered 12/8, 2012 at 22:26 Comment(2)
The death of the sending process would cause an RST on Windows. The port disappears from the server after the final FIN and ACK and possible TIME-WAIT, and not before.Ursas
What about the death of OS? What would happen in this situation?Hadhramaut

© 2022 - 2024 — McMap. All rights reserved.