How to properly close socket in both client and server (python)
It looks like what you are looking for is an graceful shutdown. First your code does not work because you are closing socket immediately after calling shutdown.
The rule is that in a graceful shutdown, both sides must be aware of the shutting down and have acknowledged it before any actually closes the socket. I only found reference for that in this MSDN page, even if it is cited on this other SO answer.
Here is a simplified presentation of what is better explained if referenced page (I do not know how to properly format tables in SO :-( ) :
- part 1 issues
shutdown(socket.SHUT_WR)
to notify it wants to terminate connexion, and continues to read from socket - part 2 receives end of file indication on socket (empty read), and can still send any remaining data - it then calls in turn
shutdown(socket.SHUT_WR)
- part 1 receives end of file on socket and knows that other part has terminated using connection
- both parts can then close the socket
Remark : it does not matter if part 2 actually closes socket before part 1 received end of file, because part 1 was already only waiting for an indication of termination : no data can have been lost
wantToLearn
Updated on June 05, 2022Comments
-
wantToLearn almost 2 years
I am writing 2 scripts in python.
- Client.py
- Server.py
There is a socket between the client and server. The scenario is this:
I am having one client that ask to close the program therefore it should inform the server which by then will inform the other client, therefore I need to close the socket from client (1) to the server and then close the socket from the server to other client (imagin yourself a game of 2 people that one ask to exit the game).I am doing it like that.In Client.py:
# send the request to the server eNum, eMsg = Protocol.send_all(self.socket_to_server, msg) if eNum: sys.stderr.write(eMsg) self.close_client() self.socket_to_server.shutdown(socket.SHUT_WR) exit(0)
then in the code of Server.py:
# get the msg from the client that calleds num, msg = Protocol.recv_all(self.players_sockets[0]) # case of failure if num == Protocol.NetworkErrorCodes.FAILURE: sys.stderr.write(msg) self.shut_down_server() # case it was disconnected if num == Protocol.NetworkErrorCodes.DISCONNECTED: print msg self.shut_down_server() technical_win = ("exit" == msg) # send the msg to the client needed to call eNum, eMsg = Protocol.send_all(self.players_sockets[1],msg) if eNum: sys.stderr.write(eMsg) self.shut_down_server() # case end of game (winning or asking to exit) if technical_win: self.shut_down_server()
while
self.shut_down_server()
is:def shut_down_server(self): # close socket of one of the player self.players_sockets[0].shutdown(socket.SHUT_RDWR) self.players_sockets[0].close() # close socket of one of the player self.players_sockets[1].shutdown(socket.SHUT_RDWR) self.players_sockets[1].close() # clean up exit(0)
When the server send the msg that the other player ask to exit the client get it and doing the same as I showed in the begining.
unfortunately it is not working because when the server perform the code:
num, msg = Protocol.recv_all(self.players_sockets[0]) # case of failure if num == Protocol.NetworkErrorCodes.FAILURE: sys.stderr.write(msg) self.shut_down_server() # case it was disconnected if num == Protocol.NetworkErrorCodes.DISCONNECTED: print msg self.shut_down_server()
it get into the second if and print
'ERROR - Could not receive a message: timed out.'
How do I fix this properly?
P.S
I am using Linux