Done Sending Not Done

write(fd, request, request_len);
shutdown(fd, SHUT_WR);                     /* sends FIN */

ssize_t k;
while ((k = read(fd, buf, sizeof buf)) > 0)
    consume(buf, k);
/* loop exits when k == 0 */

This is the standard shape of a client that streams a request of unknown length and then reads a response of unknown length. What does shutdown(fd, SHUT_WR) buy, and when does read return 0?

A

It has no effect on the wire; the client must also call shutdown(fd, SHUT_RD) or the kernel leaves the socket in ESTABLISHED indefinitely.

B

It tells the server the request is complete without tearing down the connection; read returns 0 when the server's own FIN arrives, which may be much later.

C

read returns 0 on the very next call, because a FIN closes the connection in both directions at once.

D

read returns -1 with EPIPE, since the socket can no longer be used after a FIN has been sent on it.