== An irritating limitation of listening sockets Traditional sockets implementations have an irritating limitation, at least for TCP sockets: it is impossible to gracefully and cleanly shut down listening (server) sockets. The problem is that kernels accept new TCP connections for listening sockets without asking your server; _accept()_ doesn't actually *accept* the connection, it just gives you the next one that the kernel has already accepted on your behalf. This means that to shut down cleanly, you need a two-stage process: first you tell the kernel to stop accepting new connections for you, and then you process all of the existing accepted connections. If you simply dump everything, clients will see abrupt disconnections of established connections, because from their perspective the connection is complete; their _connect()_ finished, and they can even have been sending data. Unfortunately, there's no two-stage close interface for server sockets (at least, none that I can see): * if you just _close()_ the socket, you flush the pending _accept()_ queue. * you can't un-_listen()_ by setting the backlog size to 0 or -1 or the like. * _shutdown()_ is either the same as _close()_, does nothing, or produces very peculiar results, depending on the system and the exact arguments; in no case does it cause further _connect()_ calls from clients to be refused. * ((SO_ACCEPTCONN)) is a read-only socket option. (You *can* do this with Unix domain sockets, by removing the socket file itself without closing your server socket fd.) Among other consequences, this means that protocols where the client connections and immediately starts sending data are dangerous; the client had better be prepared for the entire conversation to fail. The only way to make sure that the server is *really* there (instead of in the process of shutting down) is to wait for it to send you something, which may be why so many Internet protocols start with greeting banners from the server. (As a pragmatic matter the server can lower the risk by not closing things down until _accept()_ on a non-blocking socket returns an error, but there's still a concurrency race, just a smaller one.)