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

wan*_*arn 1 sockets runtime-error shutdown python-2.7

我正在用 python 编写 2 个脚本。

  1. 客户端.py
  2. 服务器.py

客户端和服务器之间有一个套接字。场景是这样的:
我有一个客户端要求关闭程序,因此它应该通知服务器,然后它会通知另一个客户端,因此我需要关闭从客户端 (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)
Run Code Online (Sandbox Code Playgroud)

然后在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()
Run Code Online (Sandbox Code Playgroud)

虽然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)  
Run Code Online (Sandbox Code Playgroud)

当服务器发送另一个玩家要求退出客户端的 msg 时,获取它并按照我在开始时展示的方式进行操作。

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

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()
Run Code Online (Sandbox Code Playgroud)

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

我该如何正确解决这个问题?

聚苯乙烯

我正在使用 Linux

Ser*_*sta 5

看起来您正在寻找的是正常关机。首先,您的代码不起作用,因为您在调用关闭后立即关闭套接字。

规则是在正常关闭中,双方都必须知道关闭并在任何实际关闭套接字之前确认它。我只在这个MSDN 页面中找到了参考,即使它在这个其他SO 答案中被引用。

这是一个简化的介绍,如果引用页面更好地解释(我不知道如何在 SO :-( ) 中正确格式化表格:

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

备注:第 2 部分是否在第 1 部分收到文件结尾之前实际关闭套接字并不重要,因为第 1 部分已经在等待终止的指示:不会丢失任何数据