socket remains in CLOSE-WAIT after client called shutdown()
I just noticed that when I executed the server and client from the examples directory, the socket for the client (on the server side) remains in CLOSE-WAIT. This happens because the server does not send a FIN and the TCP connection is not properly closed.
Surprisingly when you spwan the client.py for a second time the previous CLOSE-WAIT socket goes a way, but the new socket again remains in CLOSE-WAIT.
I'm not sure if this is the way it should be.
That seems strange yes... Any idea why? Could it be because of the flag to socket() that makes sure that it doesn't keep the port occupied after it's closed (keeping it for some time is standard on UNIX)?
You mean this line?
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Well, when I comment it out, the behaviour is the same.
Yes that one... Oh, strange then, really strange. I'll look into this and see if I can find something out. Are you sure you didn't end up with some (non-main-)thread hanging on to the connection?
Can you reproduce this?
The only thing that I changed is that I commented out the line
client.notify("shutdown")
in example/client.py so that the server continues serving after the client disconnects. It may be that a non-main thread hangs on the connection but that would be a bug and I didn't really look into the code.
Another strange thing which I discovered is that there are ~100 IP packets sent between the client and the server for this one simple ping/pong example. When you look at it in Wireshark you can see that more or less every byte is sent separately and ACKed by the other side.
Is this really necessary? It seems very inefficient.
No I can't! I did that. Or at least I can't see any CLOSE_WAIT in lsof -i anyway...
I have fixed the "bug" of sending a character at a time - it now buffers up to 512 bytes or one json-rpc message, whichever is smallest.
It was just sloppy programming of me not to put a buffer there...
So, exactly what did you do to detect the CLOSE_WAIT? And which exact commands did you run (and did you edit anything apart from commenting out the client.notify("shutdown")?
Ok, I did a fresh checkout and only commented out the line where the client sends the 'shutdown' to the server.
I have the following watch-command running during the whole process.
watch -n 0.5 'ss -an | grep 4712' (ss is part of the iproute2 package, it's the successor of netstat)
Then I start server.py, I can see the LISTENing socket in my watch terminal, everything as expected so far.
The I start client.py. After it finished the output of ss -na is the following:
LISTEN 0 1 :4712 * : FIN-WAIT-2 0 0 127.0.0.1:50779 127.0.0.1 :4712 CLOSE-WAIT 0 0 127.0.0.1:4712 127.0.0.1 :50779
The FIN-WAIT goes away after some time but the CLOSE-WAIT stays. Could it be that you do not close the socket on the server side properly?
I hope you can reproduce it this way.