Behavior of shutdown(sock, SHUT_RD) with TCP

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?

Best Answer:

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.

Other Answer 1:

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.

Other Answer 2:

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. 🙂

Other Answer 3:

I test shudown(sock,SHUT_RD) on Ubuntu 12.04. I find that when you call shutdown(sock,SHUT_RD) if there are no any type of data(include FIN….) in the TCP buffer, the successive read call will return 0(indicates end of stream). But if there are some data which arrived before or after shutdown function, read call will process normally as if shutdown function was not called. It seems that shutdown(sock,SHUT_RD) doesn’t cause any TCP states changed to the socket

Other Answer 4:

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).