Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
244 views
in Technique[技术] by (71.8m points)

How to properly close socket in both client and server (python)

I am writing 2 scripts in python.

  1. Client.py
  2. 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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...