【问题标题】:Close socket when game ends游戏结束时关闭套接字
【发布时间】:2015-12-29 23:14:57
【问题描述】:

我在搅拌机游戏中编写了一个脚本并使用套接字,我有一个 Server.blend 和一个 client.blend。

这是我的服务器的构造函数:

class Server:

def __init__(self, host="127.0.0.1", port= 9238):

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.socket.setblocking(False)
    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    self.socket.bind((host, port))

这是我客户的:

class Client:

def __init__(self, server_ip="127.0.0.1", server_port= 9238):

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.socket.setblocking(False)

    self.serv_addr = (server_ip, server_port)

问题是我不知道客户端什么时候退出游戏,所以我无法关闭他的套接字——是什么让使用的端口保持打开状态,所以我不能再次使用当前端口。

我有一个字典,其中包含所有客户端的所有地址,所以我尝试向所有地址发送消息,如果客户端断开连接,我将无法发送消息并使用和异常从列表中删除地址(以及头像等):

def Check_For_Disconnect(self):
    for addr in self.addr_user:
        try:
            self.socket.sendto(b"You are connected!" , addr)
        except socket.error:
            scene = logic.getCurrentScene()
            for obj in scene.objects:
                if str(obj) == "Text" and obj == self.addr_user[addr].name:
                    obj.delete()
                    del self.addr_user[addr]

我想我没有遇到异常,因为客户端的套接字仍处于打开状态,因此消息正确到达。

有人知道我该如何解决这个问题吗?

【问题讨论】:

  • 请提供一些代码 - 你如何跟踪用户的行为等等。如果你不跟踪他/她的活动,当他/她离开游戏时很难得到通知。跨度>
  • 不确定问题是什么。当客户端断开连接时,会传递一个 disconnet 事件(我假设是 TCP)。
  • 这是问题..我不使用 TCP,我已经编辑了我的问题并添加了一些代码,所以现在你可以看到我不使用它..

标签: python sockets blender


【解决方案1】:

客户端应该发送一些关于退出游戏的信息,这样服务器就知道何时关闭套接字。所以这个过程是由客户端触发的。

【讨论】:

  • 所以您的建议是向客户发送一条消息,询问他是否真的想离开?然后我就能知道他正在退出?这是一个好主意,但我仍然有一个问题,在搅拌机中,客户端可以随时按 esc 并关闭游戏。然后我不知道他离开了..
  • 您不必询问客户。如果他停止该进程,它将向服务器发送信号。客户端程序在未发送自动离开消息之前不允许退出程序。
  • 但是客户端没有关闭套接字,端口仍然打开并且他仍然可以收到消息,他无法显示它们,因为没有代码可以做到这一点。在客户端停止进程之前,他必须关闭它的套接字。我想当客户端停止套接字时正在发送信号。
  • 此外,请注意我在服务器中使用:self.socket.setblocking(False) .. 我想这就是客户端仍然连接的原因
【解决方案2】:

我找到了一个解决方案:我不知道客户端什么时候退出游戏,所以我不能关闭他的socket,我所知道的是客户端运行他的游戏时-他可以发送消息到服务器。因此,只要服务器在空中,他就向客户端询问“已连接”消息。每次服务器没有从客户端收到消息时,他都会计算一次。现在,在您确定客户端已断开连接之前,您需要执行多少计数。

这是我的接收方法:

def receive(self):

    while True:
        for k in self.addr_connected:
            if self.addr_connected[k] > 50:
                self.Remove_Client(k)
                break

        try:

            data, addr = self.socket.recvfrom(1024)

            if not addr in self.addr_user:

                user= User(data.decode())

                scene = logic.getCurrentScene()
                spawner = scene.objects['Spawner']
                avatar = scene.addObject("Avatar", spawner)
                avatar.children[0]['Text'] = user.name
                avatar['user']= user 

                self.addr_user[addr] = user
                self.addr_connected[addr] = 0

            else:
                user= self.addr_user[addr]
                try:
                    user.keyboard.updateState(pickle.loads(data))
                except:
                    data = data.decode()
                    if data == "I am connected":
                        self.addr_connected[addr] = 0
                        for k in self.addr_connected:
                            if k != addr:
                                self.addr_connected[k] += 1

        except socket.error:
            for k in self.addr_connected:
                self.addr_connected[k] += 1     
            break

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多