Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当Pyro4客户端意外断开连接时释放资源_Python_Pyro4 - Fatal编程技术网

Python 当Pyro4客户端意外断开连接时释放资源

Python 当Pyro4客户端意外断开连接时释放资源,python,pyro4,Python,Pyro4,我有一个Pyro4分布式系统,多个客户端连接到一台服务器。这些客户端连接到一个远程对象,该对象可能会在系统中分配一些资源(在我的例子中是虚拟设备) 一旦客户端断开连接(比方说因为崩溃),我需要释放这些资源。检测特定客户端与特定对象断开连接的正确方法是什么? 我试过不同的方法: 重写守护进程.clientDisconnected方法。我从这个方法中得到一个连接参数。但我无法将其与对象关联,因为我无法访问该连接所指的远程对象 使用Daemon.clientDisconnected中的Pyro4.c

我有一个Pyro4分布式系统,多个客户端连接到一台服务器。这些客户端连接到一个远程对象,该对象可能会在系统中分配一些资源(在我的例子中是虚拟设备)

一旦客户端断开连接(比方说因为崩溃),我需要释放这些资源。检测特定客户端与特定对象断开连接的正确方法是什么?

我试过不同的方法:

  • 重写
    守护进程.clientDisconnected
    方法。我从这个方法中得到一个
    连接
    参数。但我无法将其与对象关联,因为我无法访问该连接所指的远程对象
  • 使用
    Daemon.clientDisconnected
    中的
    Pyro4.current\u context
    。这不起作用,因为它是线程本地对象。如果我的池中连接的客户端比线程多,就会得到重复的上下文
  • 使用Pyro4项目提供的“usersession”示例中的
    Proxy.\u pyroAnnotations
    对我没有帮助,因为我再次从
    Pyro4.core.current\u context.annotations
    属性获取注释,该属性在调用
    守护进程.clientDisconnected
    时显示错误的注释(我想是由于线程相关的问题)
  • 在远程类中使用
    instance\u mode=“session”
    \uuuu del\uuuu
    方法(因为每个客户端都有一个单独的类实例,所以一旦客户端断开连接,该实例就应该被销毁)但是这依赖于
    \uu del\uu
    方法,正如一些Python程序员所指出的那样,该方法存在一些问题

我添加了我当前的解决方案作为答案,但我真的很想知道是否有一种更优雅的方式来使用Pyro4,因为这种情况是网络编程中经常出现的模式。

我使用
代理。_pyroHandshake
属性作为客户端的客户端ID,并覆盖
守护进程。validateHandshake
Daemon.clientDisconnected
。这样,在每个新连接上,我都会将握手数据(每个客户端都是唯一的)映射到一个连接。但我真的想知道在Pyro4中是否有一种优雅的方法来实现这一点,这是网络编程中经常出现的模式

请注意,客户端还可以扩展Pyro4.Proxy并使用_pyroAnnotations将客户端ID发送到所有远程调用,而不是将代理用作客户端的属性

class Client:

    def __init__(self):

        self._client_id = uuid.uuid4()
        self._proxy = Pyro4.Proxy("PYRO:server@127.0.0.1")
        self._proxy._pyroHandshake = self._client_id
        self._proxy._pyroBind()

    def allocate_resource(self, resource_name):
        self._proxy.allocate_resource(self._client_id, resource_name)


class Server:

    def __init__(self):

        self._client_id_by_connection = {}
        self._resources_by_client_id = {}

    def client_connected(self, connection, client_id):

        self._client_id_by_connection[client_id] = connection
        self._resources_by_client_id[client_id] = []

    def client_disconnected(self, connection):

        client_id = self._client_id_by_connection[connection]

        for resource in self._resources_by_client_id[client_id]
            resource.free()

    @Pyro4.expose
    def allocate_resource(self, client_id, resource_name)

        new_resource = Resource(resource_name)
        self._resources_by_client_id[client_id].append(new_resource)

server = Server()
daemon.register(server, objectId="server")
daemon.clientDisconnect = server.client_disconnected
daemon.validateHandshake = server.client_connected
daemon.requestLoop()

Pyro 4.63可能会有一些内置的支持,以使其更容易实现。如果您从Github克隆当前的主机,您可以在此处阅读相关内容并尝试一下。也许您可以看看这是否会使您的用例更简单?

关于
守护进程。clientDisconnected
:客户端可以访问多个对象通过其连接。因此,在这里不可能将任何内容与单个对象关联-客户端可以访问多个对象。这听起来是完美的解决方案。一旦得到一些结果,我将接受此答案。非常感谢。很高兴听到。请让我知道结果是否对您有效,以便我知道此解决方案是值得的我做了一些测试,Irmen。但是我最终发现了一些问题。不确定我是否误解了文档,或者它是否真的存在于库中。我在你的Github问题跟踪器中发布了测试场景。我在自己的系统中运行了测试。似乎是完美的解决方案。请注意最后的注释在文档部分。谢谢@Irmen。只是一个小小的提醒,Pyro 4.63现在已经发布,具有这个新功能。