我在python中编写了2个脚本。
客户端和服务器之间有一个套接字。
场景是这样的:
我有一个客户端要求关闭程序,因此它应该通知服务器,然后通知另一个客户端,因此我需要关闭从客户端(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
答案 0 :(得分:3)
看起来你正在寻找的是一个优雅的关闭。首先,您的代码不起作用,因为您在调用shutdown后立即关闭套接字。
规则是在正常关闭时,双方必须知道关闭并在实际关闭套接字之前确认它。我只在MSDN page中找到了对此的引用,即使在其他SO answer引用了它。
这是一个简化的演示文稿,如果引用页面更好地解释了什么(我不知道如何正确格式化SO :-()中的表格:
shutdown(socket.SHUT_WR)
通知它想要终止连接,并继续从套接字读取shutdown(socket.SHUT_WR)
备注:如果第2部分在第1部分收到文件结束之前实际关闭套接字并不重要,因为第1部分已经只等待终止指示:没有数据可以丢失