views:

585

answers:

4

When using a TCP socket, what does

shutdown(sock, SHUT_RD);

actually do? Does it just make all recv() calls return an error code? If so, which error code?

Does it cause any packets to be sent by the underlying TCP connection? What happens to any data that the other side sends at this point - is it kept, and the window size of the connection keeps shrinking until it gets to 0, or is it just discarded, and the window size doesn't shrink?

+1  A: 

Looking at the Linux source code, shutdown(sock, SHUT_RD) doesn't seem to cause any state changes to the socket. (Obviously, shutdown(sock, SHUT_WR) causes FIN to be set.)

I can't comment on the window size changes (or lack thereof). But you can write a test program to see. Just make your inetd run a chargen service, and connect to it. :-)

Chris Jester-Young
+3  A: 

Shutting down the read side of a socket will cause any blocked recv (or similar) calls to return 0 (indicating graceful shutdown). I don't know what will happen to data currently traveling up the IP stack. It will most certainly ignore data that is in-flight from the other side. It will not affect writes to that socket at all.

In fact, judicious use of shutdown is a good way to ensure that you clean up as soon as you're done. An HTTP client that doesn't use keepalive can shutdown the write-side as soon as it is done sending the request, and a server that sees Connection: closed can likewise shutdown the read-side as soon as it is done receiving the request. This will cause any further erroneous activity to be immediately obvious, which is very useful when writing protocol-level code.

Tom
A: 

shutdown(sock, SHUT_RD) causes any writer to the socket to receive a sigpipe signal.

Any further reads using the read system call will return a -1 and set errno to EINVAL.

The use of recv will return a -1 and set errno to indicate the error (probably ENOTCONN or ENOTSOCK).

David Harris
why would SHUT_RD affect writers? I don't see any obvious reason for it to do so (though, I suppose I always use MSG_NOSIGNAL, so that may have an impact).
Tom
Because (quoting from Wikipedia) "On POSIX-compliant platforms, SIGPIPE is the signal sent to a process when it attempts to write to a pipe without a process connected to the other end." And the shutdown(sock, SHUT_RD) statement disconnects the reader process from the pipe. To add injury to insult, the default action upon receipt of a SIGPIPE signal is for the process (i.e the writer) to terminate.
David Harris
A: 

shutdown(,SHUT_RD) does not have any counterpart in TCP protocol, so it is pretty much up to implementation how to behave when someone writes to a connection where other side indicated that it will not read or when you try to read after you declared that you wont.

On slightly lower level it is beneficial to remember that TCP connection is a pair of flows using which peers send data until they declare that they are done (by SHUT_WR which sends FIN). And these two flows are quite independent.

sacha