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

╄→尐↘猪︶ㄣ 提交于 2019-11-26 10:05:17

问题


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


回答1:


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



来源:https://stackoverflow.com/questions/27746499/how-to-properly-close-socket-in-both-client-and-server-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!