ChatGPT解决这个技术问题 Extra ChatGPT

socket.shutdown vs socket.close

I recently saw a bit of code that looked like this (with sock being a socket object of course):

sock.shutdown(socket.SHUT_RDWR)
sock.close()

What exactly is the purpose of calling shutdown on the socket and then closing it? If it makes a difference, this socket is being used for non-blocking IO.


A
Arvid

Calling close and shutdown have two different effects on the underlying socket.

The first thing to point out is that the socket is a resource in the underlying OS and multiple processes can have a handle for the same underlying socket.

When you call close it decrements the handle count by one and if the handle count has reached zero then the socket and associated connection goes through the normal close procedure (effectively sending a FIN / EOF to the peer) and the socket is deallocated.

The thing to pay attention to here is that if the handle count does not reach zero because another process still has a handle to the socket then the connection is not closed and the socket is not deallocated.

On the other hand calling shutdown for reading and writing closes the underlying connection and sends a FIN / EOF to the peer regardless of how many processes have handles to the socket. However, it does not deallocate the socket and you still need to call close afterward.


great answer, i never bothered to find out what shutdown() does :)
Can a shutdown() for read causes it to send a FIN packet? i.e. shutdown(sock_fd, 1);
Would it be smart to always call .shutdown() and on the next line .close()? Or should there be a delay in between?
@Luc Completely depends on what you're doing.
@Luc Then just close is fine as long as no other processes have a handle to the socket.
B
Bob Nadler

Here's one explanation:

Once a socket is no longer required, the calling program can discard the socket by applying a close subroutine to the socket descriptor. If a reliable delivery socket has data associated with it when a close takes place, the system continues to attempt data transfer. However, if the data is still undelivered, the system discards the data. Should the application program have no use for any pending data, it can use the shutdown subroutine on the socket prior to closing it.


D
Dale Reidy

Explanation of shutdown and close: Graceful shutdown (msdn)

Shutdown (in your case) indicates to the other end of the connection there is no further intention to read from or write to the socket. Then close frees up any memory associated with the socket.

Omitting shutdown may cause the socket to linger in the OSs stack until the connection has been closed gracefully.

IMO the names 'shutdown' and 'close' are misleading, 'close' and 'destroy' would emphasise their differences.


It does not indicate to the other end that there is no further intention to read. Shutdown for read doesn't send anything to the peer.
m
mykhal

it's mentioned right in the Socket Programming HOWTO (py2/py3)

Disconnecting Strictly speaking, you’re supposed to use shutdown on a socket before you close it. The shutdown is an advisory to the socket at the other end. Depending on the argument you pass it, it can mean “I’m not going to send anymore, but I’ll still listen”, or “I’m not listening, good riddance!”. Most socket libraries, however, are so used to programmers neglecting to use this piece of etiquette that normally a close is the same as shutdown(); close(). So in most situations, an explicit shutdown is not needed. ...


This information isn't correct. It is only ever necessary to shutdown a socket for writing if (1) you have forked the process and definitely want to send the FIN now, or (2) you are engaging in a mutual read-to-EOS protocol such that both peers close at the same time. Otherwise close() is sufficient. The Python documentation should be corrected.
C
Christian

Isn't this code above wrong?

The close call directly after the shutdown call might make the kernel discard all outgoing buffers anyway.

According to http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable one needs to wait between the shutdown and the close until read returns 0.


Not correct. The kernel will only discard outgoing buffers if the connection has been reset, which can happen if the local app hasn't read all the pending inbound data that has already arrived, or if the peer has messed with SO_LINGER, which they shouldn't do. There is no necessity to sleep either, nor even to call shutdown before close. There is a lot of misinformation out there about this matter.
R
Ray Tayek

there are some flavours of shutdown: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx. *nix is similar.


There is one 'flavour' of shutdown, and it has two options, which can be combined. Nothing here answers the actual question.
u
user306166

Shutdown(1) , forces the socket no to send any more data

This is usefull in

1- Buffer flushing

2- Strange error detection

3- Safe guarding

Let me explain more , when you send a data from A to B , it's not guaranteed to be sent to B , it's only guaranteed to be sent to the A os buffer , which in turn sends it to the B os buffer

So by calling shutdown(1) on A , you flush A's buffer and an error is raised if the buffer is not empty ie: data has not been sent to the peer yet

Howoever this is irrevesable , so you can do that after you completely sent all your data and you want to be sure that it's atleast at the peer os buffer


Shutdown does not force a flush. The buffering situation is unchanged. And if the buffer isn't empty no error is raised. The FIN is merely enqueued behind the pending data. Answer is completely incorrect.