如何正确关闭客户端和服务器中的套接字(python)

时间:2015-01-02 18:04:14

标签: sockets python-2.7 runtime-error shutdown

我在python中编写了2个脚本。

  1. Client.py
  2. Server.py
  3. 客户端和服务器之间有一个套接字。 场景是这样的:
    我有一个客户端要求关闭程序,因此它应该通知服务器,然后通知另一个客户端,因此我需要关闭从客户端(1)到服务器的套接字,然后从服务器关闭套接字其他客户(想象自己是一个人要求退出游戏的2人游戏)。

    我这样做。在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)
    

    然后在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()
    

    self.shut_down_server()是:

    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)  
    

    当服务器发送另一个玩家要求退出客户端的消息时,获取它并按照我在开始时显示的那样做。

    遗憾的是它不起作用,因为当服务器执行代码时:

    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()
    

    它进入第二个if并打印'ERROR - Could not receive a message: timed out.'

    如何正确解决此问题?

    P.S

    我正在使用Linux

1 个答案:

答案 0 :(得分:3)

看起来你正在寻找的是一个优雅的关闭。首先,您的代码不起作用,因为您在调用shutdown后立即关闭套接字。

规则是在正常关闭时,双方必须知道关闭并在实际关闭套接字之前确认它。我只在MSDN page中找到了对此的引用,即使在其他SO answer引用了它。

这是一个简化的演示文稿,如果引用页面更好地解释了什么(我不知道如何正确格式化SO :-()中的表格:

  • 第1部分发出shutdown(socket.SHUT_WR)通知它想要终止连接,并继续从套接字读取
  • 第2部分接收套接字上的文件结束指示(空读),仍然可以发送任何剩余数据 - 然后依次调用shutdown(socket.SHUT_WR)
  • 第1部分接收套接字上的文件结尾,并知道其他部分已使用连接终止
  • 然后两个部分都可以关闭套接字

备注:如果第2部分在第1部分收到文件结束之前实际关闭套接字并不重要,因为第1部分已经只等待终止指示:没有数据可以丢失