Reputation: 491
I am writing 2 scripts in python.
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
Upvotes: 3
Views: 11932
Reputation: 148900
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 :-( ) :
shutdown(socket.SHUT_WR)
to notify it wants to terminate connexion, and continues to read from socketshutdown(socket.SHUT_WR)
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
Upvotes: 8