The heart of the fix is to keep two distinct sockets for server connections, the listen socket and the connection (accept) socket. Before, the code only kept one socket and the listen socket was overwritten by the connection socket when accept() was called. By keeping track of the two sockets separately, NETACCEPTOFF can reliably cancel the listen(), which makes it possible to re-listen on the same port later.
An ancilliary change is to close the connection socket when the client initiates a half-close. This was required to not leak the connection socket by overwriting it when a new accept() call was made.
The logic still only supports one concurrent connection to the server, so multiple connections must be made in serial.